Redis数据结构与对象——压缩列表

压缩列表(ziplist)是列表和哈希键的底层实现之一。

1 压缩列表的构成

  压缩列表是Redis节约成本而开发,是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或一个整数值。
  下图表示压缩的各个组成部分及含义


  下图表示一个包含三个节点的压缩列表,列表的起始地址的指针为p,那么列表表尾节点的地址就是p加上zltail的值,即p+60。
包含是三个节点的压缩列表

2 压缩列表节点的构成

  每个压缩列表节点可以保存一个字节数组或者一个整数值。下图表示压缩列表的组成部分及含义。


压缩列表节点各个组成部分和含义

  2.1 previous_entry_length

  节点的previous_entry_length属性以字节为单位,长度为1字节或5字节,记录压缩列表前一个节点的长度。

(1) 如果前一个节点的长度小于254字节,那么previous_entry_length属性长度为1字节。
(2) 如果前一个节点的长度大于等于254字节,那么previous_entry_length属性长度为5字节。

  因为节点的previous_entry_length记录了前一个节点的长度,所以程序可以通过指针运算,根据当前节点的起始地址来计算出前一个节点的起始地址。压缩列表的从表尾向表头遍历操作就是通过这一原理实现的。只要拥有了一个指向某个节点起始地址的指针,就可以通过这个指针和这个节点的previous_entry_length属性,一个一个向前遍历,最终达到列表的表头节点。

  2.2 encoding

  节点的encoding属性记录了节点的content属性所保存数据的类型和长度:

(1) 如果是一个字节长,值的最高位是11开头的是整数编码,表示content保存的是整数值。
(2) 如果是一个字节、两个字节或者五个字节长,值的最高位为00、01或10的是字节数组编码,表示content保存的是字节数组。

  2.3 content

  节点的content属性负责保存的值,节点值可以是一个字节数组或者整数,值的类型和长度由节点的encoding属性决定。
  如下图,表示一个保存字节数组的列表节点,encoding属性的最高两个二进制位00表示节点保存的是一个字节数组。后六个二进制位001011表示字节数组的长度,即“hello world”的长度。


一个保存字节数组的列表节点

  如下图,表示一个保存整数值的列表节点,encoding属性的最高两个二进制位11表示节点保存的是一个整数值,content属性保存节点的值10086。


一个保存整数值的列表节点

3 连锁更新

  前面说过,previous_entry_length属性的长度是1个字节或5个字节,如果前一个节点的长度小于254字节,就使用1个字节保存这个长度值,反之使用5个字节保存这个长度值。
  假设在压缩列表中,有多个连续的、长度介于250字节到253字节之间的节点e1至eN,如下图所示:


  由于每个节点的长度均小于254,所以每个节点的previous_entry_length属性所需的长度都是1个字节。
  此时,在表头插入一个新节点,这个节点的长度大于254,由于 e1的previous_entry_length属性仅长1字节,没有办法保存新节点的长度,所以长须需要将e1节点的previous_entry_length属性从原来的1个字节扩展为5个字节长。

  由于e1的previous_entry_length属性添加了4个字节,导致e1节点的长度也大于254,所以导致e2节点previous_entry_length属性也要从原来的1个字节扩展为5个字节长...直到eN为止。
  Redis在特殊情况下产生连续多次空间扩展操作称之为“连锁更新”(cascade update),下图表示了这一过程。
连锁更新过程

  除了新添加节点会造成连锁跟新之外,删除节点也可能引发连锁更新。
  如下图所示的压缩列表,e1至eN都是大小介于250字节到253字节的节点,big节点时长度大于254的节点,small节点也是小于254字节的节点。small节点使用5个字节保存big节点的长度,如果此时将small节点删除,那么需要e1节点保存big节点的长度,但是e1节点的previous_entry_length属性是1个字节,需要扩展...,导致的情况和插入的情况一致。
删除节点引发的连锁更新

  因为连锁更新在最坏的情况下需要对压缩列表执行N次空间重分配操作,而每次空间分配的最坏复杂度为O(N),所以连锁更新的最坏复杂度为O(N2)。
  但是,要造成连锁更新的可能性非常小。首先需要多个连续的、长度均介于250字节至253字节的节点,这种情况实际上并不多见。同时,即使出现了连锁更新,但是只要被更新的节点数量不多,就不会对性能造成任何影响。

4 小结

(1) 压缩列表是一种为节约内存而开发的顺序型数据结构,被作为列表键和哈希键的底层实现。
(2) 压缩节点可以包含任意个节点,每个节点可以保存一个字节数据或整数值。
(3) 添加新节点到压缩列表,或者从压缩列表中删除节点,可能引发连锁更新操作,但是这操作出现的几率并不高。

  本文完


  注:本文参考《Redis设计与实现》,如发现错误,请指正!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • 构成 压缩列表是 Redis 为了节约内存而开发的, 由一系列特殊编码的连续内存块组成的顺序型(sequentia...
    来年花惜阅读 2,211评论 0 2
  • 最近读了《Redis 设计与实现》,知道了Redis在存储对象中做了很多的优化,利用各种不同的存储结构实现, 减少...
    mecury阅读 451评论 0 0
  • 压缩列表时列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项都是小整数或者长度较短的字符串...
    杰哥长得帅阅读 1,022评论 0 0
  • 压缩列表(ziplist)是列表键和哈希键的底层实现之一。 当一个列表键只包含少量列表项, 并且每个列表项要么就是...
    颜灏_2181阅读 331评论 0 0
  • 一 晚上嗓子疼一直睡不着觉,在床上翻来覆去了很久,但不想吵到其他人睡觉,就躲在被窝...
    长安风起时阅读 169评论 2 2