让 Redis zset 支持多条件排序

本文探讨了如何扩展 Redis zset 的排序能力,使其支持多条件排序。介绍了三种方法:1) 利用 key 排序,将不变的维度写入 key;2) 通过二进制分段存储各个维度,确保不损失精度;3) 直接拆分 double 进行维度划分。这些方法适用于不同场景,如数据量、精度要求和计算复杂度等。
摘要由CSDN通过智能技术生成

Redis 的 zset 可以很方便的实现一个排行榜,但是只通过单纯的 score 和 key 排序并不满足一些需要多条件排序的需求。本文将会介绍一些通过计算让 zset 的 score 支持多条件排序的方法。

一些需求中经常要我们实现一个排行榜,数据量少的话可以使用 RDB 数据库排序,数据量大可以自己实现算法或者使用 NoSQL 数据库排序,NoSQL 数据库中最方便的可能就是利用 Redis 的 zset 来实现了。 例如要实现一个玩家成就点数的排行榜:

>zadd r 100 A"1">zadd r 200 B"1">zadd r 200 C"1">zadd r 300 D"1">zrange r 0 -1 withscores1)  "A"2)  "100"3)  "B"4)  "200"5)  "C"6)  "200"7)  "D"8)  "300"       

其中 B 和 C 的分数是一样的,这时我们可能想让先达到对应分数的人排在前面,相当于增加了一个排序维度。这时直接用 score 就不能实现了,需要做一些转换,这里分享几个我会用到的方法。

实现方法

假设我们需要一个三个维度的排序,第一维度是具体的数值,第二个维度是一个是否标志位,第三个维度是时间戳。其中氪金的(0否1是)和时间早的排序靠前。

以下是原始数据:

玩家  成就  是否氪金  时间戳A    100  1        1571819021259B    200  0        1571819021259C    200  1        1571819021259D    400  0        1571819021259E    200  1        1571810001259

1. 利用 key 排序

如果后两个维度初始化后就不再变化的话,可以利用 Redis 的排序特性,将不变的维度写到 key 里,这样 score 相同时会用 key 来进行排序。

# 这里反转时间戳(9999999999999 - 1571810001259),让时间早的排在前面>zadd r 100 A-1-8428180978740"1">zadd r 200 B-0-8428180978740"1">zadd r 200 C-1-8428180978740"1">zadd r 400 D-0-8428180978740"1">zadd r 200 E-1-8428189998740"1">zrange r 0 -1 withscores 1)  "A-1-8428180978740" 2)  "100" 3)  "B-0-8428180978740" 4)  "200" 5)  "C-1-8428180978740" 6)  "200" 7)  "E-1-8428189998740" 8)  "200" 9)  "D-0-8428180978740" 10)  "400"

以上就是第一种方法了,实现起来非常简单。


score 存储格式

在介绍下两种方法前先来看看 zset 的 score 是怎么存储的,能保留多少精度,直接看跳表 node 的结构。

/* * 跳跃表节点 */typedef struct zskiplistNode {    // 成员对象    robj *obj;    // 分值    double score;    // 后退指针    struct 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值