使用Redis实现用户积分及TopN排行榜功能

举报
JavaEdge 发表于 2021/06/04 00:07:42 2021/06/04
【摘要】 1 需求 添加积分 在用户签到的基础上添加用户积分,签到 1 天送 10 积分,连续签到 2 天送 20 积分,3 天送 30 积分,4 天以上均送 50 积分。积分排行榜 2 表设计 利用MySQL保存积分数据 这类似于一张日志表,因此数据量很大,想要统计用户积分做排行榜时,表数据可能如下: 3 实现TopN积分排行榜 MySQL 方案 统计 SQL ...

1 需求

  • 添加积分
    在用户签到的基础上添加用户积分,签到 1 天送 10 积分,连续签到 2 天送 20 积分,3 天送 30 积分,4 天以上均送 50 积分。
  • 积分排行榜

2 表设计

  • 利用MySQL保存积分数据

    这类似于一张日志表,因此数据量很大,想要统计用户积分做排行榜时,表数据可能如下:

3 实现TopN积分排行榜

MySQL 方案

  • 统计 SQL 获取排行榜前二十,如果重复排名,则后一位就靠后
  • 业务逻辑

缺点

看上去实现简单,数据量小时运行也没大问题,但当数据量超过一定量后,就会出现很大延迟,毕竟 MySQL 查询要消耗大量 IO。

因为 t_diner_points 本质上是一张日志表,记录了所有用户的积分记录,因此直接去数据库统计的话会有如下问题:
• SQL 编写复杂
• 数据量大,执行统计 SQL 慢
• 高并发下会拖累其他业务表的操作,导致系统变慢

Redis方案

使用 Sorted Sets 保存用户的积分总数,因为 Sorted Sets 有 score 属性,能够方便保存与读取,使用指令:

# 添加元素的分数,如果member不存在就会自动创建
ZINCRBY key increment member 
# 按分数从大到小进行读取
zrevrange key
# 根据分数从大到小获取member排名
zrevrank key member

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
diner_points("diner:points", "diner用户的积分")

  
 
  • 1

代码实现

添加积分记录

  • 当将用户积分记录插入数据库后,同时利用ZINCRBY指令,将数据存入 Redis,不使用ZADD是因为当用户不存在记录要插入,而且存在时需要将分数累加。

积分排行榜

从 Redis 根据 diner:points 的 key 按 score 的排序进行读取。使用 Redis 的ZREVRANGE命令,但ZREVRANGE只返回 member,不返回 score,在 RedisTemplate 的 ZSetOperations 中的 reverseRangeWithScores(key, start, end),start 从 0 开始,返回的是 member 和 score,底层是将ZREVRANGEZSCORE指令进行组装,使用起来非常方便。

  • 个人排名
    使用REVRANKZSCORE命令读取。

  • 从 redis 获取排行榜

优点

  • Redis 本身内存数据库,读取性能高
  • Sorted Sets 底层是 SkipList + ZipList 既能保证有序又能对数据进行压缩存储
  • Sorted Sets 操作简单,几个命令搞定

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/113354018

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。