程序员子龙(Java面试 + Java学习) 程序员子龙(Java面试 + Java学习)
首页
学习指南
工具
开源项目
技术书籍

程序员子龙

Java 开发从业者
首页
学习指南
工具
开源项目
技术书籍
  • 基础

  • JVM

  • Spring

  • 并发编程

  • Mybatis

  • 网络编程

  • 数据库

  • 缓存

    • Redis

      • Redis基础知识
      • redis底层数据结构
      • 发布和订阅
      • 分分钟搞懂布隆过滤器,亿级数据过滤算法你值得拥有!
      • 缓存和数据库一致性解决方案
      • 详解redis的bitmap
      • 面试常问使用缓存出现的问题
      • Redis hot key 发现以及解决办法
      • Redis实现排行榜功能实战
        • 前言
        • ZSet概述
          • 2、加分值
          • 4、查看直播间人数
          • 6、周榜
        • JAVA实现排行榜
        • 总结
      • Redis 管道技术——Pipeline
      • 11、RedisTemplate使用最详解(一)--- opsForValue()
      • RedisTemplate使用最详解(二)--- opsForList()
      • RedisTemplate使用最详解(三)--- opsForHash()
      • RedisTemplate使用最详解(四)--- opsForSet()
      • RedisTemplate使用最详解(五)--- opsForZSet()
      • Redis分布式锁-这一篇全了解(Redission实现分布式锁完美方案)
      • 建议收藏!看完全面掌握,最详细的Redis总结
      • Redis分布式锁-这一篇就够了
      • 《进大厂系列》系列-Redis常见面试题
    • 本地缓存

  • 设计模式

  • 分布式

  • 高并发

  • SpringBoot

  • SpringCloudAlibaba

  • Nginx

  • 面试

  • 生产问题

  • 系统设计

  • 消息中间件

  • Java
  • 缓存
  • Redis
程序员子龙
2024-03-21
目录

Redis实现排行榜功能实战

# 前言

在日常的服务器开发过程中,经常会遇到排行榜的需求。这里我们主要讨论使用redis zset来实现一般的常用排行榜。也就是单key排行榜,分数为整数,一般长度不过万。

# ZSet概述

Redis的ZSet(Sorted Set)是一种有序集合,它结合了Set和SortedList的特性,成员是唯一的,且按照成员的分数(score)进行从小到大排序。在ZSet中,每个元素都会关联一个分数,分数可以重复,但元素不能重复。这使得ZSet非常适合用于实现排行榜等场景。

每个直播间都有粉丝的排行榜,可以通过key+直播间id来作为redis的key。例如broadcast:20210108231。每个直播间的观众按照点赞数排序。则观众刚刚进入直播间即可通过ZADD添加排行榜。

张三观众进入直播间。
李四进入直播间
ZADD [key] [score] [value]
1
2
3

ZADD broadcast:20240108231 1 zhangsan ZADD broadcast:20240108231 1 lisi

# 2、加分值

`李四`送了直播间两颗小红心。李四分值`加2`。
`ZINCRBY [key] increment [member]
1
2

ZINCRBY broadcast:20240108231 2 lisi

3、展示榜单 通过如上指令对直播间分值进行设置之后,得到redis的value如下:

127.0.0.1:6379> ZRANGE broadcast:20240108231 0 -1 WITHSCORES
1) "zhaoliu"
2) "2"
3) "wangwu"
4) "5"
5) "lisi"
6) "8"
7) "zhangsan"
8) "10"

1
2
3
4
5
6
7
8
9
10

# 4、查看直播间人数

ZCARD key 返回集合数量。

127.0.0.1:6379> zcard  broadcast:20240108231
(integer) 4
1
2

5、离开直播间 张三离开直播间,则删除对应key。 ZREM [key] [value]

127.0.0.1:6379>  ZREM broadcast:20240108231 zhangsan
(integer) 1
127.0.0.1:6379>  ZREVRANGE broadcast:20240108231 0 2
1) "lisi"
2) "wangwu"
3) "zhaoliu"

1
2
3
4
5
6
7

# 6、周榜

真实场景中肯定会有时间段的划分,例如查看日榜、周榜、月榜。只需要按照最小的单位按照时间区分成不同的集合,最后求出这些集合的并集即可。

ZADD broadcast:1 10 zhangsan ZADD broadcast:1 10 lisi ZADD broadcast:2 5 zhangsan ZADD broadcast:2 5 wangwu 如此,得到两个zset集合,最后得到两个集合的并集。 ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

127.0.0.1:6379> ZUNIONSTORE broadcast:week:1 2 broadcast:1 broadcast:2
(integer) 3
127.0.0.1:6379> ZRANGE broadcast:week:1 0 -1 WITHSCORES
1) "wangwu"
2) "5"
3) "lisi"
4) "10"
5) "zhangsan"
6) "15"

1
2
3
4
5
6
7
8
9
10

WEIGHTS 可以设置每个集合的权重,意为在原来集合分数乘权重得到输出集合的值。 两个集合并集时,如果有相同的key,则可以通过 SUM|MIN|MAX 进行控制。默认为SUM。

# JAVA实现排行榜

要实现一个排行榜,我们需要做以下几件事:

  • 创建一个ZSet,其中包含用户ID和对应的分数。
  • 获取排行榜数据,并按照分数降序排列。

以下是一个简单的Java代码示例,展示了如何使用Jedis库来实现基于Redis的ZSet的秒级排行榜


public class RedisZSetRank{
    
    @Autowired
    private RedisTemplate redisTemplate;

    // 添加用户分数到排行榜
    public void addScore(String userId, double score) {
         redisTemplate.opsForZSet().add("ranking",userId,score);

    }

    // 获取排行榜数据
    public Set<String> getRanking() {
        // 获取前10名
        return redisTemplate.opsForZSet().reverseRange("ranking", 0, 10); 
    }
    
    // 查看某条记录的排名
    public Long ranking(String code) {
        Long ranking = redisTemplate.opsForZSet().rank("ranking", code);
        if (ranking != null) {
            //有序集合的索引是从0开始的,所以查询出来的排名要+1。
            return ranking + 1;
        }
        return ranking;
    }
    
    public static void main(String[] args) {

        // 添加用户分数
        rank.addScore("user1", 100);
        rank.addScore("user2", 200);

        // 获取排行榜数据
        Set<String> rankingData = rank.getRanking();
        for (String userId : rankingData) {
            System.out.println("User ID: " + userId);
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

这样就实现了简单的排行榜。

# 总结

Redis 的有序集合 Sorted Set中的成员是唯一的,但分数(score)却可以重复,这一点恰恰可以被我们用来实现排行榜的功能。

上次更新: 2024/03/30, 14:19:47
Redis hot key 发现以及解决办法
Redis 管道技术——Pipeline

← Redis hot key 发现以及解决办法 Redis 管道技术——Pipeline→

最近更新
01
一个注解,优雅的实现接口幂等性
11-17
02
MySQL事务(超详细!!!)
10-14
03
阿里二面:Kafka中如何保证消息的顺序性?这周被问到两次了
10-09
更多文章>
Theme by Vdoing | Copyright © 2024-2024

    辽ICP备2023001503号-2

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式