跳跃表/压缩列表/有序集合

跳跃表

有序链表

有序链表是链表中的所有元素按照升序或者降序排列。如下图所示:


image.png

如果要查找上图中的25。得从头开始一个一个往下遍历对比。那么时间复杂度将会是O(n)。对有序链表的插入和删除操作,也得先遍历找到对应的元素或者位置才能操作,插入和删除基本不耗时间,查找才是性能瓶颈。

跳跃表

对有序链表查询性能的优化。
将有序链表中的部分节点抽出来分几层,每一层也是一个有序链表。查找的时候从最高层开始找,当到达某个节点的时候,如果next的值大于要查找的值或者next是null,则去下面一层继续查找,以此类推。


image.png

如上图中的跳跃表,如果要查找元素29:

  1. 首先去第二层查找,当到达元素25到时候,它到next是null,所以进入第一层;
  2. 元素25在第一层的next是33,大于元素29,所以进入第0层;
  3. 元素25在第0层的next是29,匹配找到。

压缩列表

压缩列表ziplist本质上就是一个字节数组。数组是一种线性的数据结构。每一个元素可以是整数或者字节数组。注意:ziplist本身是一个字节数组,它的元素也可以是字节数组。
因为数组在插入/删除的时间复杂度,所以ziplist一般在元素数量不多的情况下使用。另外因为它的元素可以存储字节数组,字节数组对于上层应用来说就是字符串,所以在字符串比较短的情况下才使用ziplist。

ziplist的结构

image.png

zlbytes: 表示压缩列表总的字节数,占4个字节。那么压缩列表总的字节数最多是2^32-1 个字节。
zltail: 压缩列表的尾部元素,占4个字节。
zllen: 压缩列表的元素个数,占2个字节。那么压缩列表总的元素个数组多是2^16-1个。
entryX:压缩列表里面的元素,可以是整数或者字节数组,长度不限。
zlend:压缩列表的结尾,固定值为0xFF,占1个字节
所以根据压缩列表的结构可以知道,它的总大小不能超过(2^32 - 1)个字节。它的元素个数不能超过(2^16 - 1)。

ziplist里面entry的结构:

image.png

previous_entry_length: 表示前一个元素的字节长度。占1个或者5个字节。如果前一个元素的字节长度小于254字节时,占1个字节;否则就占5个字节。占5个字节的时候,第一个字节是固定的0xFE,后面四个字节才是表示长度。所以这么说来,单个元素的字节数也不能超过(2^32 - 1)。
encoding: 表示当前元素(也就是content的内容)存储的是字节数组还是整数。长度可变。

应用

在有序集合zset的实现里面,跳跃表和压缩列表都有用到。
根据上面都描述,压缩列表的使用场景一般是短字符串,且元素个数不能太多。所以在zset里面有几个配置:
zset-max-ziplist-entries: 默认值128, 当元素个数小于这个值都时候使用压缩列表。否则使用跳跃表。
zset-max-ziplist-value:默认值64,当每个元素的字符串长度小于这个值的时候使用压缩列表,否则使用跳跃表。
满足这两个条件中的任意一个条件,就会转换到跳跃表。而转换到跳跃表之后,即便把元素删除,也不好回退到压缩列表。

你可能感兴趣的:(跳跃表/压缩列表/有序集合)