Redis是一种高性能的键值型数据库,它支持多种数据结构,其中一种是list类型。list类型可以存储一个有序的字符串列表,类似于Java中的LinkedList或Python中的list。list类型的优点是可以在列表的两端进行快速的插入和删除操作,支持阻塞和非阻塞的读取方式。
list 是一个有序的字符串列表,它按照插入顺序排序,并且支持在两端插入或删除元素。一个 list 类型的键最多可以存储 2^32 - 1 个元素。
redis3.2
以后,list 类型的底层实现只有一种结构,就是quicklist。版本不同时,底层实现是不同的,下面会讲解。
list 类型的应用场景主要是实现队列和栈,比如:
在讲解list结构之前,需要先说明一下list结构编码的更替,如下
Redis3.2
之前,list使用的是linkedlist
和ziplist
Redis3.2~Redis7.0
之间,list使用的是quickList
,是linkedlist
和ziplist
的结合Redis7.0
之后,list使用的也是quickList
,只不过将ziplist
转为listpack
,它是listpack、linkedlist结合版在Redis3.2
之前,linkedlist
和ziplist
两种编码可以选择切换,它们之间的转换关系如图
ziplist转为linkedlist的条件可在redis.conf配置
list-max-ziplist-entries 512
list-max-ziplist-value 64
quicklist
存储了一个双向列表,每个列表的节点是一个ziplist
,所以实际上quicklist
并不是一个新的数据结构,它就是linkedlist
和ziplist
的结合,然后被命名为快速列表。
ziplist内部entry个数可在redis.conf配置
list-max-ziplist-size -2
# -5: 每个ziplist最多为 64 kb <-- 影响正常负载,不推荐
# -4: 每个ziplist最多为 32 Kb <-- 不推荐
# -3: 每个ziplist最多为 16 Kb <-- 最好不要使用
# -2: 每个ziplist最多为 8 Kb <-- 好
# -1: 每个ziplist最多为 ![请添加图片描述](https://img-blog.csdnimg.cn/2f226105c23d4249ac727b7dc2b172f5.png)
4 Kb <-- 好
# 正数为ziplist内部entry个数
ziplist通过特定的LZF压缩算法来将节点进行压缩存储,从而更进一步的节省空间,而很多场景都是两端元素访问率最高,我们可以通过配置list-compress-depth
来排除首尾两端不压缩的entry个数。
list-compress-depth 0
# - 0:不压缩(默认值)
# - 1:首尾第 1 个元素不压缩
# - 2:首位前 2 个元素不压缩
# - 3:首尾前 3 个元素不压缩
# - 以此类推
和Hash结构一样,因为ziplist
有连锁更新问题,redis7.0
将ziplist
替换为listpack
,下面是新quickList的结构图
Redis中listpack源码
typedef struct quicklist {
quicklistNode *head;
quicklistNode *tail;
unsigned long count; /* 所有列表包中所有条目的总数,占用16 bits,最大65536 */
unsigned long len; /* quicklistNode 的数量 */
signed int fill : QL_FILL_BITS; /* 单个节点的填充因子 */
unsigned int compress : QL_COMP_BITS; /* 不压缩的端节点深度;0=off */
unsigned int bookmark_count: QL_BM_BITS;
quicklistBookmark bookmarks[];
} quicklist;
typedef struct quicklistNode {
struct quicklistNode *prev;
struct quicklistNode *next;
unsigned char *entry;
size_t sz; /* 当前entry占用字节 */
unsigned int count : 16; /* listpack元素个数,最大65535 */
unsigned int encoding : 2; /* RAW==1 or LZF==2 */
unsigned int container : 2; /* PLAIN==1 or PACKED==2 */
unsigned int recompress : 1; /* 当前listpack是否需要再次压缩 */
unsigned int attempted_compress : 1; /* 测试用 */
unsigned int extra : 10; /* 备用 */
} quicklistNode;
listpack内部entry个数可在redis.conf配置
List-Max-listpack-size -2
# -5: 每个listpack最多为 64 kb <-- 影响正常负载,不推荐
# -4: 每个listpack最多为 32 Kb <-- 不推荐
# -3: 每个listpack最多为 16 Kb <-- 最好不要使用
# -2: 每个listpack最多为 8 Kb <-- 好
# -1: 每个listpack最多为 4 Kb <-- 好
# 正数为listpack内部entry个数
Redis list类型是一种可以存储一个有序的字符串列表的数据结构,它有以下特点:
Redis内存优化——String类型介绍及底层原理详解
Redis内存优化——Hash类型介绍及底层原理详解
Redis内存优化——List类型介绍及底层原理详解
Redis内存优化——Set类型介绍及底层原理详解
Redis内存优化——ZSet类型介绍及底层原理详解
Redis内存优化——Stream类型介绍及底层原理详解
Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解
Redis的三种持久化策略及选取建议