zsetredis中常用的数据结构,一般使用场景是有序集合,排行榜等有序的需求我们会考虑使用。

背景: 最近也是做了相关的需求,用户发动态,将最新动态中的图片,视频或音频资源收集起来,列表中会展示用户最新4条动态的资源缩略图。因为动态还有个审核,所以 一般采集的时候会按审核的时间点采集,但展示却得按照创建时间展示。因此采用了zset的方案,score的值为创建时间,当审核完成时,会将该动态的资源信息以member存储至 zset中,取的时候,按照score(创建时间)由大到小读取

方案实施

  1. 存储,简单使用zadd命令,将动态资源信息(一个结构体,json格式化后以字符串形式)存储至zset中,createdAtscore
1
2
3
4
# ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN
# 将一个或多个成员元素及其分数值加入到有序集当中
# ZADD file fileInfo createdAt
-> ZADD file "{url:'xxx.jpg',type:1}" 1635661958
  1. 维持zset大小,因为只需要取最新4条动态的资源,因此,对于旧的资源信息,可以删除4名开外的动态信息
1
2
3
4
5
6
# ZREMRANGEBYRANK key start stop
# 移除有序集中,指定排名(rank)区间内的所有成员。
-> ZRemRangeByRank file 0 -5
# 因为默认是按从小到大排序的,我们如果要取最新的4条动态,需要从排名最小的元素开始删除,
# 0代表排名最旧的,排最前的,-5表示排名倒数第5的,
# 当zset中的元素超过4时,-5其实就相当于0,所以整个语句相当于删除第4名之后的动态资源信息
  1. 获取从大到小顺序的最新4条动态
1
2
3
# ZREVRANGE key start stop [WITHSCORES]
# 按分数值递减(从大到小)来排列
-> ZREVRANGE file 0 3

不足之处

因为member的值中有url,有类型等信息,zset的member的长度是过大的,这就导致了并不能用上quickList,只能使用上skipList

1
2
zset-max-ziplist-entries  保存的元素少于128个
zset-max-ziplist-value    保存的元素大小都小于64字节

当不满足以上的任何一个条件时,会采用skipList,显然,我们的存储是超过64字节的。跳表的相对成本来说,是高于quickList不少的。

数据结构

zset的底层数据结构有两种,一种是ziplist(压缩列表),一种是skiplist(跳表)

ziplist(压缩列表)

skiplist(跳表)

常用命令

  1. ZADD 向有序集合添加一个或多个成员,或者更新已存在成员的分数
1
2
-> ZADD key score1 member1 [score2 member2]
-> ZADD userAge 28 jiang [30 hua]
  1. ZCARD key

使用场景

避免踩坑