前言
List是一个按加入时序排序的数据结构,Redis采用quicklist(双端链表) + ziplist 作为List的底层实现
使用双端链表的缺点
Redis并没有直接采用双端链表存储数据,因为每两个节点需要两个指针连接,在64位系统下,每个指针所占内存为8byte,如果链表存储大量小数据,那么指针的开销就会很浪费。
ziplist
是一个连续的内存空间,分为head,data,end三部分,一个ziplist在内存中各部分依次为
zlbytes zltail zlen <entry1, entry2, entryn> zlend:255
entry: prerawlen len data
含义:
zlbytes:32bit,表示ziplist占用的字节总数;
zltail:32bit,表示ziplist表中的最后一项,在ziplist中的偏移字节数,通过ziptail可以快速找到最后一项,从而可以快速在list尾部执行push或pop操作;
zlen:16bit,表示ziplist中数据项个数;
zend:8bit,ziplist最后一个字节,是一个结束标记,值固定为255;
entry:表示真正存放数据的数据项,长度不定;
prerawlen:表示前一个数据项数据长度,当长度小于254,则用一个字节表示;否则用一个值为254的字节标记 + 4个字节表示真实长度,加起来即5个字节。
len:数据项长度;
data:真实数据存储,根据len值不同,共有13种情况。
ziplist优点
Redis对内存敏感,连续紧凑的数据结构能节省内存。
ziplist缺点
当需要往链表中间插入数据,要对部分数据进行迁移,进行大量内存分配,数据量大的时候效果不好。
优化
使用quicklist,对ziplist进行分段。
quicklist内存结构
head - tail - count - length
head: 指向quicklist的头结点,指针为quicklistNode;
tail:指向quicklist的尾结点,指针为quicklistNode;
count:quicklist中ziplist个数
length:quicklist中ziplist个数
quicklistNode: prev - next - zl - length
prev:指向前一个quicklistNode;
next:指向下一个quicklistNode;
zl:指向ziplist地址;
length:ziplist元素个数;
配置
设置每个ziplist容量大小,-2代表容量为8kb
# Lists are also encoded in a special way to save a lot of space.
# The number of entries allowed per internal list node can be specified
# as a fixed maximum size or a maximum number of elements.
# For a fixed maximum size, use -5 through -1, meaning:
# -5: max size: 64 Kb <-- not recommended for normal workloads
# -4: max size: 32 Kb <-- not recommended
# -3: max size: 16 Kb <-- probably not recommended
# -2: max size: 8 Kb <-- good
# -1: max size: 4 Kb <-- good
# Positive numbers mean store up to _exactly_ that number of elements
# per list node.
# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),
# but if your use case is unique, adjust the settings as necessary.
list-max-ziplist-size -2
设置quicklist数据压缩范围,提升数据存储效率
# Lists may also be compressed.
# Compress depth is the number of quicklist ziplist nodes from *each* side of
# the list to *exclude* from compression. The head and tail of the list
# are always uncompressed for fast push/pop operations. Settings are:
# 0: disable all list compression
# 1: depth 1 means "don't start compressing until after 1 node into the list,
# going from either the head or tail"
# So: [head]->node->node->...->node->[tail]
# [head], [tail] will always be uncompressed; inner nodes will compress.
# 2: [head]->[next]->node->node->...->node->[prev]->[tail]
# 2 here means: don't compress head or head->next or tail->prev or tail,
# but compress all nodes between them.
# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]
# etc.
list-compress-depth 0
默认设置为0,表示所有数据都不压缩,当设置为1时,表示头尾两个quicklistNode不压缩,其他压缩;
当设置为2时,表示头两个和尾部两个quicklistNode不压缩,其他压缩;
因为list常用于存储热点数据,比较关注头尾数据,中间数据较少关注,可以进行压缩。
网友评论