Redis-SortedSet

有序集合每个字符串元素都关联到一个双精度64位的浮点型数字字符串score,里面的元素总是通过score进行着排序,因此它是可以检索的一系列元素

默认升序排列,即通过命令ZRANGE实现;如果要按照降序排列,需要通过命令ZREVRANGE实现

当score即得分一样时,按照字典顺序对member进行排序,字典排序用的是二进制,它比较的是字符串的字节数组,所以实际上是比较ASCII码

底层结构

Ziplist

有序集合对象的编码可以是ziplist或者skiplist,同时满足以下条件时使用ziplist编码:

  • 元素数量小于128个
  • 所有member的长度都小于64字节

以上两个条件的上限值可通过zset-max-ziplist-entries和zset-max-ziplist-value来修改

ziplist编码的有序集合使用紧挨在一起的压缩列表节点来保存,第一个节点保存member,第二个保存score

ziplist内的集合元素按score从小到大排序,score较小的排在表头位置

Skiplist

skiplist编码的有序集合底层是一个命名为zset的结构体,而一个zset结构同时包含一个字典和一个跳跃表

跳跃表按score从小到大保存所有集合元素,而字典则保存着从member到score的映射,这样就可以用O(1)的复杂度来查找member对应的score值,虽然同时使用两种结构,但它们会通过指针来共享相同元素的member和score,因此不会浪费额外的内存

向有序集合中添加score和element  时间复杂度 O(logN)

获取element的分数   时间复杂度O(1)

自增element的分数  时间复杂度O(1)

返回有序集合中元素的个数  时间复杂度O(1)

多维度排序

以手机应用商店的热门榜单排序为例:首先按照APP的下载量倒序排序,如果下载量一样,则按照最后更新时间倒序排列

SortedSet排序因子score,它是一个双精度64位的浮点型数字字符串

我们如何实现多维度排序?

构造一个特殊的score,以这个案例为例,排序影响因子是下载量和更新时间,那么我们可以构造一个这样特殊的浮点类型的score:整数部分就是下载量,小数部分就是最后更新时间戳

假设有5个app的下载量和最后更新时间分别如下(说明:更新时间只精确到秒):

wechat-下载量:12000000,最后更新时间:1564022201;其score为:12000000.1564022201
qq-下载量:12000000,最后更新时间:1564022222;其score为:12000000.1564022222
tiktok-下载量:9808900,最后更新时间:1563552267;其score为:9808900.1563552267
taobao-下载量:11006600,最后更新时间:1564345601;其score为:11006600.1564345601
alipay-下载量:11006600,最后更新时间:1564345600;其score为:11006600.1564345600

接下来,我们通过如下命令将这5个APP用SortedSet数据类型保存到Redis中:

zadd TopApp 12000000.1564022201 wechat 12000000.1564022222 qq 9808900.1563552267 tiktok 11006600.1564345601 taobao 11006600.1564345600 alipay
保存后,我们看一下排序结果是否符合我们的预期:
127.0.0.1:6379> zrevrange TopApp 0 -1
1) "qq"
2) "wechat"
3) "taobao"
4) "alipay"
5) "tiktok"

猜你喜欢

转载自blog.csdn.net/qq_35508033/article/details/109434621