赞
踩
压缩列表是 Redis 为了节约内存而开发的一种内存紧凑型数据结构。它由连续的内存块组成,类似于数组。压缩列表主要用于 Redis 中 List 对象、Hash 对象和 Zset 对象在元素数量较少或元素值不大的情况下作为底层数据结构。
然而,压缩列表也有一些缺点:
压缩列表由多个节点组成,每个节点存储一个数据元素。其表头和节点的具体结构如下:
压缩列表的表头包含三个字段:
压缩列表的结束标记是一个固定值 0xFF
(十进制 255),用于标记压缩列表的结束点。
压缩列表的每个节点包含三部分内容:
encoding
决定。prevlen 的空间大小根据前一个节点的长度值决定:
prevlen
属性需要用 1 字节的空间来保存这个长度值。prevlen
属性需要用 5 字节的空间来保存这个长度值。encoding 的空间大小根据数据是字符串还是整数,以及字符串的长度有关:
encoding
会使用 1 字节的空间进行编码。encoding
会使用 1 字节、2 字节或 5 字节的空间进行编码。encoding
编码的前两个 bit 表示数据的类型,后续的其他 bit 标识字符串数据的实际长度。这种设计思想正是为了节省内存,通过根据数据的大小和类型进行不同的空间分配,实现内存的高效利用。
当压缩列表新增某个元素或修改某个元素时,如果空间不够,压缩列表占用的内存空间就需要重新分配。而当新插入的元素较大时,可能会导致后续元素的 prevlen
占用空间发生变化,从而引起连锁更新问题,导致每个元素的空间都要重新分配,造成访问压缩列表性能的下降。
具体来看,当我们在压缩列表中插入一个长度大于等于 254 字节的新节点,可能会引发连锁更新问题。例如,将一个长度大于等于 254 字节的新节点加入到压缩列表的表头节点:
prevlen
属性只有 1 个字节大小,无法保存新节点的长度,此时需要对压缩列表的空间进行重新分配,并将 e1 节点的 prevlen
属性从 1 字节扩展为 5 字节。prevlen
属性也必须从 1 字节扩展至 5 字节。这种在特殊情况下产生的连续多次空间扩展操作被称为「连锁更新」,类似多米诺骨牌效应,第一张牌倒下后,推动了第二张牌倒下,依次类推。
由于压缩列表需要进行空间扩展操作,这就需要重新分配内存,因此连锁更新一旦发生,会导致压缩列表占用的内存空间多次重新分配,直接影响到压缩列表的访问性能。
因此,虽然压缩列表紧凑型的内存布局能节省内存开销,但是如果保存的元素数量增加,或元素变大,会导致内存重新分配,最糟糕的是会引发「连锁更新」的问题。
压缩列表(ziplist)是 Redis 为了节约内存而开发的一种紧凑型数据结构。它由连续的内存块组成,类似于数组。压缩列表主要用于 Redis 中元素数量较少或元素值不大的 List 对象、Hash 对象和 Zset 对象。
压缩列表的表头包含三个字段:
压缩列表的结束标记是一个固定值 0xFF
(十进制 255),用于标记压缩列表的结束点。
压缩列表的每个节点包含三部分内容:
encoding
决定。prevlen 的空间大小根据前一个节点的长度值决定:
prevlen
属性需要用 1 字节的空间来保存这个长度值。prevlen
属性需要用 5 字节的空间来保存这个长度值。encoding 的空间大小根据数据是字符串还是整数,以及字符串的长度有关:
encoding
会使用 1 字节的空间进行编码。encoding
会使用 1 字节、2 字节或 5 字节的空间进行编码。encoding
编码的前两个 bit 表示数据的类型,后续的其他 bit 标识字符串数据的实际长度。这种设计思想正是为了节省内存,通过根据数据的大小和类型进行不同的空间分配,实现内存的高效利用。
当压缩列表新增某个元素或修改某个元素时,如果空间不够,压缩列表占用的内存空间就需要重新分配。而当新插入的元素较大时,可能会导致后续元素的 prevlen
占用空间发生变化,从而引起连锁更新问题,导致每个元素的空间都要重新分配,造成访问压缩列表性能的下降。
具体来看,当我们在压缩列表中插入一个长度大于等于 254 字节的新节点,可能会引发连锁更新问题。例如,将一个长度大于等于 254 字节的新节点加入到压缩列表的表头节点:
prevlen
属性只有 1 个字节大小,无法保存新节点的长度,此时需要对压缩列表的空间进行重新分配,并将 e1 节点的 prevlen
属性从 1 字节扩展为 5 字节。prevlen
属性也必须从 1 字节扩展至 5 字节。这种在特殊情况下产生的连续多
次空间扩展操作被称为「连锁更新」,类似多米诺骨牌效应,第一张牌倒下后,推动了第二张牌倒下,依次类推。
由于压缩列表需要进行空间扩展操作,这就需要重新分配内存,因此连锁更新一旦发生,会导致压缩列表占用的内存空间多次重新分配,直接影响到压缩列表的访问性能。
因此,虽然压缩列表紧凑型的内存布局能节省内存开销,但是如果保存的元素数量增加,或元素变大,会导致内存重新分配,最糟糕的是会引发「连锁更新」的问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。