手把手教你使用 Java 和 Redis 实现排行榜!
- 2020 年 4 月 8 日
- 笔记
编辑:业余草 来源:https://www.xttblog.com/?p=4937
前言
排行榜作为互联网应用中几乎必不可少的一个元素,其能够勾起人类自身对比的欲望,从而来增加商品的销量。排行榜的实现方式基本大同小异,大部分都基于 Redis 的有序集合 sorted set 来实现。不久前,负责开发一个活动,就有排行榜这个需求,笔者也使用 Redis 进行了实现。本文通过了商品销售排行榜这一模型,来进行演示。
需求
- 按照商品销量进行排行
- 可以获得指定商品的排名
- 显示实时销售动态情况
需求分析
分析需求,以上这些都可以通过 Redis 的有序集合相关命令进行实现,首先看一下使用到的具体 Redis 命令。
redis> ZADD bangdan 1 "one" (integer) 1 # 对有序集合中指定成员的分数加上增量 redis> zadd bangdan 1 "one" 4 "three" 3 "two" (integer) 2 # 将一个或多个成员以及分数加入到有序集合中 redis> zrange bangdan 0 1 1) "one" 2) "three" # 按照 score 升序排列 ,取出前两名 redis> zscore bangdan three "4" # 获得榜单中指定元素的score redis> zrank bangdan one (integer) 0 # 在升序榜中的名次 第一返回0 # 第三个需求需要使用 Redis 的 list 来进行实现 redis> LPUSH dynamic abc (integer) 1 # 向队列左侧头部 push 数据 redis> LINDEX dynamic 0 "abc" # 通过索引获取列表中的元素 redis> LTRIM dynamic 0 2 "abc" # 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
排行榜预览
按照需求开发,最后的效果如下:

下面我们通过 Java 实现它!
引入依赖
项目中使用到了 Redis,因此需要引入相关依赖,为了简明演示,这里没有使用 JedisPool。
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency>
主要代码
1、页面上点击一次购买按钮,则对该手机的销量加 1,同时将销售动态添加到队列当中。
jedis.zincrby(Constants.SALES_LIST, 1, String.valueOf(phoneId)); jedis.lpush(Constants.BUY_DYNAMIC, msg);
2、获得排行榜。
// 按照scope升序排名,取出前五 jedis.zrevrangeWithScores(Constants.SALES_LIST, 0, 4);
3、获得指定手机的排名情况。
jedis.zrevrank(Constants.SALES_LIST, String.valueOf(phoneId));
4、获得销售动态,此处只取 3 条,同时队列只保存最新的 20 条动态。
List<DynamicVO> dynamicList = new ArrayList<>(); for (int i = 0; i < 3; i++) { String result = jedis.lindex(Constants.BUY_DYNAMIC, i); if (StringUtils.isEmpty(result)) { break; } String[] arr = result.split(Constants.separator); long time = Long.valueOf(arr[0]); String phone = arr[1]; DynamicVO vo = new DynamicVO(); vo.setPhone(phone); vo.setTime(StringUtil.showTime(new Date(time))); dynamicList.add(vo); } jedis.ltrim(Constants.BUY_DYNAMIC, 0, 19);
5、因为排行榜这种实时性比较强的数据,更新比较快,个人觉得没有必要进行持久化,如果 Redis 的排行榜数据丢失,可以通过代码重新计算排行,通过 zadd 命令,重新添加到 Redis 中即可。
Map<String, Double> map = new HashMap<>(); map.put("1", 4.0); map.put("2", 2.0); map.put("3", 3.0); jedis.zadd(Constants.SALES_LIST, map);
上面是主要的实现代码,还有不少细节需要完善。