Redis学习(5)-zset

Redis基础篇–zset(有序列表)

zset

内部实现: 类似于Java语言里SortedSet和HashMap的结合体。它的内部实现用的是一种叫做"跳跃列表"的数据结构。

用途举例

zset可以用来存储粉丝列表,value值是粉丝的用户ID,score是关注时间,便可以对粉丝列表按关注时间进行排序。

zset可以用来存储学生的成绩,value值是学生的ID,score是他的考试成绩,我们对成绩按分数进行排序就可以得到他的名次。

常见命令:
zadd books 9.0 python  		#添加一个元素,score为9.0
zrange books 0 -1		#按score排序列出,参数区间为排名范围
zrevrange 0 -1			#按score逆序列出,参数区间为排名范围
zcard books			#相当于count()
zscore books python 		#获取指定value的score,内部score使用double类型进行存储,所以存在小数点精度问题
zrank books python 		#排名
zrangebyscore books 0 8.91	#根据分值区间遍历zset
zrangebyscore books -inf 8.91 withscores #根据分值区间(-∞,8.91]遍历zset,同时返回分值。inf代表infinite,无穷大的意思
zrem books python		#删除value
跳跃列表

使用跳跃列表的前提:zset需要支持随机的插入和删除,所以不宜使用数组来表示。用链表表示,但是同时又需要按照score进行排序,需要找插入点,通常会使用二分查找,但是二分查找的对象必须是数组。所以单独的链表或数组都不足以支撑zset的需求。

跳跃列表类似于层级制,最下面一层的所有元素都会串起来。然后每隔几个元素挑选出一个代表,再将这几个代表使用另外一层指针串起来。然后在这些代表里再挑出二级代表,再串起来。最终就形成了金字塔结构。
在这里插入图片描述

内部结构
struct zslnode {
	string		value;
	double		score;
	zslnode*[]	forwards;               /* 多层连接指针 */
	zslnode		* backward;             /* 回溯指针 */
}

struct zsl {
	zslnode			* header;       /* 跳跃列表头指针 */
	int			maxLevel;       /* 跳跃列表当前的最高层 */
	map<string, zslnode*>	ht;             /* hash结构的所有键值对 */
}
查找过程

从header的最高层开始遍历找到第一个节点(最后一个比"我"小的元素),然后逐层降到最底层进行遍历就找到了期望的节点。
在这里插入图片描述
参考:Redis内部数据结构之跳表

随机层数

对于每一个新插入的节点,都需要调用一个随机算法给它分配一个合理的层数。直观上期望的目标是50%的概率被分配到Level1,25%的概率被分配到Level2,12.5%的概率被Level3,以此类推,2的-63次方的概率被分配到最顶层。

元素排名

redis在skiplist的forward指针上进行了优化,给每一个forward指针都增加了span属性,span是跨度的意思,表示从当前层的节点沿着forward指针跳到下一个节点中间会跳过多少个节点。redis在插入、删除操作时会小心翼翼地更新span值的大小

struct zslforward {
	zslnode * item;
	long	sapn; /* 跨度 */
}

这样当我们要计算一个元素的排名时,只需要将"搜索路径"经过的所有节点的跨度span值进行叠加就可以算出元素的最终rank值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值