redis之Zset 底层原理

Zset 有两种编码格式 , 一种是ziplist(双向链表的形式), skiplist(跳跃表的形式),Zset会根据相应的规则来选择编码格式,

一、ziplist (压缩列表)

1.条件 :

  1. 元素个数小于128个
  2. 元素的长度小于64

ziplist采用的是双向的链表的结构实现, 且是一个特殊的双向链表,为啥特殊呢,因为链表的设计采用了连续的内存空间

2.结构:

在这里插入图片描述

在这里插入图片描述

<zlbytes> <zltail> <zllen> <entry> <entry> ... <entry> <zlend>

zbytes :
整个记录了ziplist占用的字节数 (32位)
ztail :
最后一个数据实体的元素的的偏移量(32位) 这就使得我们能更加快速的找到最后一个元素,它能以O(1)的时间复杂度在表的两端提供push和pop操作
zlen :
数据实体的元素的个数 (16位),当数据量个数超出2^16-1 时,zlen会将16位全部置为1,
这时zlen 不再表示当前ziplist的数据元素个数, 此时要想知道元素个数就只能通过遍历的方式去得到。
zlentry:
ziplist中的数据实体元素
zlend :
ziplist的结束标志位 固定位数值255

不足:
因为内存地址是需要连续的,所以大量的数据的时候不适合,如果是大量的数据的话就会需要大量的连续的内存地址,这可能也是是为啥呀限制,数据超过128后要转出为跳跃表

3.zentry得结构组成

在这里插入图片描述

prerawlen :
前一个数据实体的长度,通过当前地址-prerwalen可以快速的找到前一个数据
len:
当前实体的数据长度
endcoding :
编码格式
data :
实际的数据 <value,score>

二、skiplist (跳跃表)

条件:

当不满足ziplist的条件的时候就会使用skiplist的方式,即不满足(元素个数小于128,数据长度小于64)

skiplist 结构其实由一个 score 跳跃链表 + 一个字典构成
字典中记录了每个score —>对应的value 的地址 ,只要通过跳跃表查到对应的score 就可以 在字典 中根据score 快速找到对应的value

结构:

在这里插入图片描述

与标准的跳跃表不同, 每次插入数据的时候会随机的产生一个层数,因为如果是严格的跳跃表的话,相邻两节点的层高之比固定为2:1, 这样的话就会存在在加入数据的时候,为了保证层高固定比例而必须去调整后面的节点,就会影响查找的效率
产生随机层数的源码:

#define ZSKIPLIST_MAXLEVEL 32 
#define ZSKIPLIST_P 0.25 

int zslRandomLevel(void) {
    int level = 1;
    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
        level += 1;
    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

每一个节点平均的指针数:=1/(1-p)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值