Redis有序集合对象(Zset)使用ziplist和skiplist

标题首先明确一下几点基本常识:

  • Redis常见的5种数据类型:String(字符串)、List(列表)、Hash(哈希)、Set(集合)、ZSet(有序集合),这五种常见的数据类型,本质上对应着五种对象,即字符串对象、列表对象、哈希对象、集合对象、有序集合对象。
  • 在Redis中,任意一个对象都具有五种属性

[1] type ====> 类型对应基本数据类型。例如Redis_String 对应字符串,Redis_List对应列表
[2] encoding ====> 编码。编码方式决定了对象的底层的数据结构,一个对象至少有两种编码方式
[3] prt ====> 指针。指向由编码决定的数据结构,数据结构中往往包含有所存的数据
[4] refcount ====> 引用计数。这个属性主要是为了实现redis中的内存回收机制
[5] lru ====> 最近最少使用。用来解决对象的空转时长,同时也会被用于当缓冲达到最大值,再向其中添加数据时,应该删除什么数据。

有序结合(ZSet)对象详解

上述说过,一个对象的底层的数据结构是由对象的编码方式决定的,而ZSet的编码方式有两种

  • ziplist
  • skiplist
    上述两种数据结构的底层实现见书籍 《redis设计与实现》。
    有序结合底层s

ZipList

使用压缩连表时,要保证集合中的数据有序,会将key放在前面一位,然后将key所对应value放在key的后一位。这样就能够保证集合的有序。
在这里插入图片描述

SkipList

使用跳跃链表时,由于跳跃链表本来就是有序的,直接使用即可。
跳表数据结构见《Redis设计与实现》P39

当有序集合对象同时满足以下两个条件时,对象使用压缩链表编码:

  • 有序集合保存的元素数量小于128个;
  • 有序集合保存的所有元素成员的长度都小于64字节;

如果不满足上述两个条件,那么ZipList会转化为SkipList,同时,当后面的SkipList的元素数量和元素成员的长度满足要求时,也不会回退为ZipList。

重点

当使用SkipList实现ZSet时,ptr所指向的zset数据结构中包含了一个skiplist和dict结构。其中dict结构中创建了一个从SkipList对象到score的映射。通过dict可以实现O(1)时间复杂度查找key所对应的value。

那么为什么不直接使用字典或者skipList实现Zset呢?

  • 当直接使用字典的时候,虽然可以做到查询key-value的时间复杂度O(1),但是字典本身是无序的,要排序至少也需要O(Nlog(N))。
  • 当直接使用SkipList时,虽然可以做到有序,但是查询key-value至少也需要O(logN)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值