压缩列表是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,且每个列表项要么是小整数值,要么是长度较短的字符串,Redis则使用压缩列表作为列表键的底层实现。当一个哈希键只包含少量键值对,且每个键值对要么是小整数值,要么是长度较短的字符串,Redis则使用压缩列表作为哈希键的底层实现。
压缩列表是由一系列特殊编码的连续内存块组成的顺序型数据结构,是为了节约内存开发的。,以下为压缩列表的组成部分:
zlbytes | bltail | zllen | entry1 | entry2 | entry3 | ... | entryN | zlend |
每个压缩列表的节点可以保存一个字节数组或一个整数值。以下为压缩列表节点的组成部分:
previous_entry_length | encoding | content |
前面提到每个节点的previous_entry_length属性记录了前一个节点的长度,当前一个节点长度小于254字节时,previous_entry_length长度为1字节,否则previous_entry_length长度为5字节。当压缩列表的每个节点的长度介于250-253字节之间时,向压缩列表添加一个长度大于254的节点 ,其下一个节点的previous_entry_length属性长度仅为1字节,此时需要扩张为5字节,而这一操作又会引起下一个节点的previous_entry_length需要进行扩张...Redis将这种在特殊情况下产生的连续多次空间扩展操作称为连锁更新。
连锁更新在最坏情况下需要对压缩列表执行N次空间重分配,而每次重分配最坏复杂度为O(N),因此连锁更新的最坏复杂度为O()。
虽然连锁更新的复杂度很高,但是造成性能问题的几率是很低的: