Chapter 10.利用Redis Zset实现双维度排行榜

本文探讨如何利用Redis ZSet数据类型实现双维度排行榜,包括分值和时间的排序。文章介绍了ZSet的底层结构、操作过程以及针对需求提出的三种实现思路:加结构、借member、拆/合score,并详细分析了各个方案的优缺点,最终选择了利用double的浮点计算来实现高精度的分值和时间排序。
摘要由CSDN通过智能技术生成

欢迎来到「我是真的狗杂谈世界」,关注不迷路

背景


最近需要将遇到的几个排行需求点抽出来做一个独立的通用排行组件,整理记录一下。

核心需求


  • 能获得连续的部分的榜单:比如前100名、第300~400名的用户以及分值
  • 能获得任意单用户信息:比如用户A的分值与当前排名
  • 能操作榜单单用户分值:比如为用户A增加3分
  • 上述功能要求实时
  • 分值相同时,要求按照达到分值时间的先后排序,先达到分值的用户排在前面
  • 分值是整数(或类似金额这种有限位小数,也可以看为整数),业务上一般高精度小数无场景意义

思考过程


说白了就是排序问题,相关的算法和结构有很多了,可问题是总不能自己从零开始实现吧(也不是不可以)~~

那么在现有的存储介质上很容易想到Redis的ZSet数据类型(MySQL不是今天的主题,假装想不到咳咳)

Redis ZSet


底层结构与操作过程

ZSet数据类型的主要数据结构是跳表,具有多层级结构(因此对内存要求稍稍高一点),具体的结构和操作过程在「Tool 1.Redis捣腾系列」中继续捣腾。

相关功能情况

现在只关注上述需求用到的几个操作是否支持以及性能开销情况:

  • ZADD/ZINCRBY: O(log(N))
  • ZSCORE: O(1)
  • ZCARD: O(1)
  • ZRANGE/ZREVRANGE: O(log(N)+M);N为有序集的基数,而M为结果集的基数
  • ZRANK/ZREVRANK: O(log(N))

O(log(N))的时间复杂度理论上完全可以扛住上亿数据的并发查询(当然并不建议真的在生产环境这么干)。

O(log(N)+M)需要特别注意,M是线性增长的,需要严格控制上限

一些特点

ZSet在使用上是member->score结构:

  • member: 被排序的标识,也是默认的第二排序维度(score相同时,redis以member的字典序排列)
  • score: 被排序的分值,存储类型是double

双维度问题


如果直接按照上述用法进行使用,那么只有第一排序维度score是我需要的,虽然有第二排序维度member,而需要的第二排序维度是时间。那怎么办呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值