java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java Redis微博热搜

Java使用Redis实现微博热搜功能

作者:w_l666

在社交平台上,热搜功能是一个非常重要的组成部分,它展示了当前最热门的话题,帮助用户迅速了解最受关注的事件,Redis 是一个高性能的键值存储系统,通常用于缓存和实时数据存储,本文将通过 Java 结合 Redis 实现一个简化版的微博热搜功能,需要的朋友可以参考下

介绍

在社交平台上,热搜功能是一个非常重要的组成部分。它展示了当前最热门的话题,帮助用户迅速了解最受关注的事件。在微博等平台上,热搜榜单通常是实时变化的,可能会根据用户的互动数据(如搜索频次、点赞量、评论数等)动态调整。

Redis 是一个高性能的键值存储系统,通常用于缓存和实时数据存储,特别适用于实现类似热搜榜单这样的功能。本文将通过 Java 结合 Redis 实现一个简化版的微博热搜功能,展示如何使用 Redis 提供的高效数据结构,如 SortedSet(有序集合)来维护热搜榜单。

 热度的计算方式,不同的产品的热度计算方式不同:

例如:

热度=评论数+转发数+点赞数 

热度=搜索量+点击量

热搜排行榜可以分为:当前小时的热搜榜,当天的热搜榜,当月的热搜榜,当前周的热搜榜等等。

思路: 一般情况下,我们按照存储每个小时的小时榜,为最小单位。  同理,当天的热搜榜,就是这一天24小时的小时榜合并后的榜单。当月的热搜榜就是,这个月每天的热搜榜合并后的榜单。

1. Redis 数据结构介绍

在实现热搜功能时,Redis 提供的 SortedSet(有序集合)是非常合适的。SortedSet 会根据分数(score)对成员(member)进行排序,适用于我们要根据热度(例如搜索频次、点赞数等)排序展示的场景。

2.当前小时的key的设定思路:

1.使用当前的时间戳来生成唯一的 key,通常使用 YYYY-MM-DD-HH 作为 key 的格式,这样每天每小时的数据都会有独立的 key。

例如:当前时间为 2024-12-10 07:25:21,那么对应的 key 为 2024-12-10-07。

2.当前时间的毫秒的时间(T),当前小时唯一key=T/1000*60*60;

例如:当前时间为2024-12-10 16:10:40=1733818240000  ,那么对应的key就是:1733818240000 /1000*60*60=481,616

以上两种方式,都可以获取到当前时间的唯一的key。

3.代码实现

1. 引入依赖

在你的 pom.xml 中加入以下依赖来使用 Redis 和 Jedis:

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>4.2.3</version>
    </dependency>
</dependencies>

主要需要实现的功能:热搜的小时榜,天榜,月榜的榜单的实现。

首先编写redis的基本操作的工具类:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
import java.util.Set;
 
public class RedisUtil {
    private static JedisPool pool;
 
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(50);
        config.setMaxIdle(10);
        config.setMinIdle(5);
        config.setTestOnBorrow(true);
        pool = new JedisPool(config, "localhost", 6379);  // Redis 地址
    }
 
    public static Jedis getJedis() {
        return pool.getResource();
    }
 
    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
 
    public static void incrementSearchCount(String key,String topic) {
        Jedis jedis = getJedis();
        try {
            // 使用 Redis 的 ZINCRBY 命令递增话题的热度
            jedis.zincrby(key, 1, topic);
        } finally {
            close(jedis);
        }
    }
 
    public static Set<String> getTopSearch(int topN) {
        Jedis jedis = getJedis();
        try {
            // 使用 Redis 的 ZREVRANGE 命令获取热搜榜单
            return jedis.zrevrange("hot_search", 0, topN - 1);
        } finally {
            close(jedis);
        }
    }
}

热搜的增加,每次都是单个增加的,此处不做解释。我们主要研究,如何查询,小时榜,天榜,月榜的数据。 

具体代码如下:

    @Autowired
    private RedisTemplate redisTemplate;
 
    /**
     * 更新天的热搜数据
     */
    public void updateDaySearch(){
        long hour = System.currentTimeMillis()/(1000*60*60);
        //小时key的前缀
        String hourPrefix = "search:hour";
        //天的key
        String dayPrefix = "search:day";
        //计算最近24小时的key的集合
        ArrayList<Object> dayKeys = new ArrayList<>();
        //统计近24小时的key的集合
        for (int i = 1; i < 23; i++) {
            String key = hourPrefix+(hour-i);
            dayKeys.add(key);
            //设置当天的key 40天过期,防止资源的浪费
            redisTemplate.expire(key,40, TimeUnit.DAYS);
        }
        //将近24小时的key的值进行合并
        //(redisTemplate.opsForZSet()。unionAndStore(a,b,c);把a,b 两个zset合并储存到c集合中)
        redisTemplate.opsForZSet().unionAndStore(hourPrefix+hour,dayKeys,dayPrefix);
        log.info("*********************进行天数据的更新************************");
    }
 
    public void updateMonthSearch(){
        long hour = System.currentTimeMillis()/(1000*60*60);
        //小时key的前缀
        String hourPrefix = "search:hour";
        //天的key
        String monthPrefix = "search:day";
        //计算最近24小时的key的集合
        ArrayList<Object> monthKeys = new ArrayList<>();
        //统计近24小时的key的集合
        for (int i = 1; i < 24*30-1; i++) {
            String key = hourPrefix+(hour-i);
            monthKeys.add(key);
        }
        //将近30天的key的值进行合并
        redisTemplate.opsForZSet().unionAndStore(hourPrefix+hour,monthKeys,monthPrefix);
        log.info("***************进行月数据的更新*********************");
    }
 
    /**
     * 更新最近7天的数据
     */
    public void updateWeekSearch(){
        long hour = System.currentTimeMillis()/(1000*60*60);
        //小时key的前缀
        String hourPrefix = "search:hour";
        //周的key
        String weekPrefix = "search:week";
        //计算最近24小时的key的集合
        ArrayList<Object> weekKeys = new ArrayList<>();
        //统计近24小时的key的集合
        for (int i = 1; i < 24*7-1; i++) {
            String key = hourPrefix+(hour-i);
            weekKeys.add(key);
        }
        //将近30天的key的值进行合并
        redisTemplate.opsForZSet().unionAndStore(hourPrefix+hour,weekKeys,weekPrefix);
        log.info("************进行周数据的更新******************");
    }
 
    /**
     * 定时器每小时调用一次次方法进行,小时榜,天榜,周榜,月榜的更新
     */
    public void updateAllSearch(){
        //TODO 此方法建议使用定时框架,quartz ,xxl-job等进行定时调用
        updateDaySearch();
        updateWeekSearch();
        updateMonthSearch();
    }

4. 优化和扩展

  1. 热搜榜单过期策略:可以设置 Redis 中有序集合的过期时间,定期清理不再热门的关键词。
  2. 多维度排序:除了搜索次数外,可以根据时间窗口(例如过去一小时、一天内的搜索量)来做更加复杂的排序。
  3. 高并发优化:为了避免频繁的 Redis 操作影响性能,可以考虑将热搜数据批量更新或者使用消息队列来异步处理。

总结

通过以上的实现,我们展示了如何使用 Java 和 Redis 来实现一个简单的微博热搜功能。通过 Redis 的有序集合,我们能够高效地记录和排序搜索关键词的热度,并在用户请求时实时返回当前最热门的话题。

这种基于 Redis 的热搜功能不仅适用于微博,实际上可以广泛应用于各种需要统计热门话题或关键词的场景,如新闻网站、视频平台等。

以上就是Java使用Redis实现微博热搜功能的详细内容,更多关于Java Redis微博热搜的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文