首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

redis源码之list结构的实现

关于redis的list的常用命令就不多说了 常用的命令lpush,rpush,lpop,rpop,lrangge等,这个不错过多的演示,相信研究源码的同学应该都知道这些,唯一要说的就是在redis中有BRPOP等命令,这个是通过redisDb中的blocking_keys和ready_keys来实现,当然这个不是咱们这篇文章需要讨论的重点

typedef struct redisDb {
    dict *dict;                /* The keyspace for this DB   字典数据结构,非常重要*/
    dict *expires;             /* Timeout of keys with a timeout set   过期时间*/
    dict *blocking_keys;       /* Keys with clients waiting for data (BLPOP)  list一些数据结构中用到的阻塞api*/
    dict *ready_keys;          /* Blocked keys that received a PUSH */
    dict *watched_keys;        /* WATCHED keys for MULTI/EXEC CAS  事务相关处理 */
    int id;                    /* Database ID */
    long long avg_ttl;         /* Average TTL, just for stats */
    unsigned long expires_cursor;/* Cursor of the active expire cycle. */
    list *defrag_later;        /* List of key names to attempt to defrag one by one, gradually. */
} redisDb;

对于redis的list来说,list是一个有序(按照加入的时序来排序)的数据结构,redis采用quicklist(双端链表)和ziplist作为list的底层实现 我们先来看看ziplist的结构图

具体各个属性的含义都在图片中有所说明,其实ziplist就是一个非常紧凑的数据结构,非常节省空间,但是它也存在对应的问题。比如我们在新加一个元素的时候,我们需要重新分配一块内存空间,然后再把数据全部拷贝过来,如果数据量小还好说,数据量大了非常影响性能,所以redis中在处理list的时候引入了quicklist的数据结构

其实quicklist的实现也比较简单,就是用了一个双向链表把各个ziplist给连接了起来。那么问题来了,每个quicklistNode中的ziplist是多大呢?根据什么来拆分呢?在redis.conf中

# 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     //单个ziplist节点最多存储8kb,超过则进行分裂,将数据存储在新的ziplist节点中

双向链表的问题就是会造成很多不连续的内存碎片,于是就需要尽量减少list的片段,就需要进行压缩


# 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代表从头节点往后走一个,尾节点往前走一个不用压缩,2、3、4以此类推  这个目的主要是减少内存的碎片
下一篇
举报
领券