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

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

介绍

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

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

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

例如:

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

热度=搜索量+点击量

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

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

1. Redis 数据结构介绍

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

  • SortedSet(zset):是一个有序的集合,每个元素都有一个分数(score),Redis 会自动根据分数对元素进行排序。适合实现需要排序的场景,如热搜榜单、排行榜等。

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微博热搜的资料请关注脚本之家其它相关文章!

相关文章

  • Java实现文件和base64流的相互转换功能示例

    Java实现文件和base64流的相互转换功能示例

    这篇文章主要介绍了Java实现文件和base64流的相互转换功能,涉及Java文件读取及base64 转换相关操作技巧,需要的朋友可以参考下
    2018-05-05
  • SpringBoot使用FreeMarker模板发送邮件

    SpringBoot使用FreeMarker模板发送邮件

    这篇文章主要为大家详细介绍了SpringBoot使用FreeMarker模板发送邮件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • Java线程池并发执行多个任务方式

    Java线程池并发执行多个任务方式

    这篇文章主要介绍了Java线程池并发执行多个任务方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • MyBatis存储过程、MyBatis分页、MyBatis一对多增删改查操作

    MyBatis存储过程、MyBatis分页、MyBatis一对多增删改查操作

    本文通过一段代码给大家介绍了MyBatis存储过程、MyBatis分页、MyBatis一对多增删改查操作,非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-11-11
  • eclipse老是自动跳到console解决办法

    eclipse老是自动跳到console解决办法

    eclipse启动服务后,想看一些properties信息或者别的,但老是自动跳转到console页面,本文给大家介绍了解决办法,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-03-03
  • 一篇文章帮你搞懂什么是java的进程和线程

    一篇文章帮你搞懂什么是java的进程和线程

    这篇文章主要介绍了java 线程详解及线程与进程的区别的相关资料,网上关于java 线程的资料很多,对于进程的资料很是,这里就整理下,需要的朋友可以参考下
    2021-08-08
  • Java中四种引用详解

    Java中四种引用详解

    这篇文章主要为大家介绍了Java中的四种引用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • idea中创建jsp项目的详细实战步骤

    idea中创建jsp项目的详细实战步骤

    才学javaWeb,以防自己忘记创建项目的过程,所以浅浅的记录一下吧,下面这篇文章主要给大家介绍了关于idea中创建jsp项目的详细步骤,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 浅谈JAVA8给我带了什么——流的概念和收集器

    浅谈JAVA8给我带了什么——流的概念和收集器

    这篇文章主要介绍了JAVA8流的概念和收集器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • spring boot项目中MongoDB的使用方法

    spring boot项目中MongoDB的使用方法

    前段时间分享了关于Spring Boot中使用Redis的文章,除了Redis之后,我们在互联网产品中还经常会用到另外一款著名的NoSQL数据库MongoDB。下面这篇文章主要给大家介绍了关于在spring boot项目中MongoDB的使用方法,需要的朋友可以参考下。
    2017-09-09

最新评论