Java使用Redis实现微博热搜功能
作者:w_l666
介绍
在社交平台上,热搜功能是一个非常重要的组成部分。它展示了当前最热门的话题,帮助用户迅速了解最受关注的事件。在微博等平台上,热搜榜单通常是实时变化的,可能会根据用户的互动数据(如搜索频次、点赞量、评论数等)动态调整。
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. 优化和扩展
- 热搜榜单过期策略:可以设置 Redis 中有序集合的过期时间,定期清理不再热门的关键词。
- 多维度排序:除了搜索次数外,可以根据时间窗口(例如过去一小时、一天内的搜索量)来做更加复杂的排序。
- 高并发优化:为了避免频繁的 Redis 操作影响性能,可以考虑将热搜数据批量更新或者使用消息队列来异步处理。
总结
通过以上的实现,我们展示了如何使用 Java 和 Redis 来实现一个简单的微博热搜功能。通过 Redis 的有序集合,我们能够高效地记录和排序搜索关键词的热度,并在用户请求时实时返回当前最热门的话题。
这种基于 Redis 的热搜功能不仅适用于微博,实际上可以广泛应用于各种需要统计热门话题或关键词的场景,如新闻网站、视频平台等。
以上就是Java使用Redis实现微博热搜功能的详细内容,更多关于Java Redis微博热搜的资料请关注脚本之家其它相关文章!