Redis----List

List简介

List也是Redis类型五巨头之一,就是一个列表,你可以从列头和列尾操作它,顺序为你的插入顺序,可重复。

List的使用

  1. lpush key value : 向队列key的队头插入value
  2. rpush key value : 向队列key的队尾插入value
  3. lpop key : 从队列key取出队头元素
  4. rpop key : 从队列key取出队尾元素
  5. lrange key start stop : 取出列表key中从start到stop的的元素,从0开始
  6. lindex key index : 取出列表key中第index个的元素
  7. linsert key before/after value1 value2 : 向列表key的value1值之前或之后插入value2元素
  8. llen : 返回列表key的长度
  9. lrem key count value : 删除列表key中count个值为value的元素
  10. ltrim key start stop : 删除列表key中从start到stop之外的元素,从0开始
  11. lset key index value : 更新列表key中的第index个元素的值为value
  12. lpushx key value : 将value插入已存在的列表key中,列表key不存在则不操作

List的底层数据结构

在redis 3.2之前的版本,根据列表的大小(512)和存储的值大小(64byte)来决定底层的数据结构,ziplist ---> linkedlist。但是在之后的版本,redis优化了列表的底层数据存储结构,改为使用quicklist结构来存储列表。

quicklist的结构

/* quicklistNode is a 32 byte struct describing a ziplist for a quicklist.
 * We use bit fields keep the quicklistNode at 32 bytes.
 * count: 16 bits, max 65536 (max zl bytes is 65k, so max count actually < 32k).
 * encoding: 2 bits, RAW=1, LZF=2.
 * container: 2 bits, NONE=1, ZIPLIST=2.
 * recompress: 1 bit, bool, true if node is temporarry decompressed for usage.
 * attempted_compress: 1 bit, boolean, used for verifying during testing.
 * extra: 12 bits, free for future use; pads out the remainder of 32 bits */
typedef struct quicklistNode {
    //前驱节点
    struct quicklistNode *prev; 
    //后继节点
    struct quicklistNode *next; 
    // 保存的数据 压缩前ziplist 压缩后压缩的数据
    unsigned char *zl; 
    // 压缩列表的大小
    unsigned int sz;
    // 压缩列表中元素个数
    unsigned int count : 16; 
    // 编码方式 1 raw  2 lzf
    unsigned int encoding : 2; 
    // 容器类型 1为none 2为压缩列表
    unsigned int container : 2; 
    // 解压标记,当查看一个被压缩的数据时,需要暂时解压,标记此参数为1,之后再重新进行压缩
    unsigned int recompress : 1;
    // 节点是否因为太小不需要压缩
    unsigned int attempted_compress : 1;
    // 扩展字段
    unsigned int extra : 10;
} quicklistNode;

/* quicklistLZF is a 4+N byte struct holding 'sz' followed by 'compressed'.
 * 'sz' is byte length of 'compressed' field.
 * 'compressed' is LZF data with total (compressed) length 'sz'
 * NOTE: uncompressed length is stored in quicklistNode->sz.
 * When quicklistNode->zl is compressed, node->zl points to a quicklistLZF */
typedef struct quicklistLZF {
    // 压缩后长度
    unsigned int sz;
    // 压缩后的数据存放数组
    char compressed[];
} quicklistLZF;

/* quicklist is a 32 byte struct (on 64-bit systems) describing a quicklist.
 * 'count' is the number of total entries.
 * 'len' is the number of quicklist nodes.
 * 'compress' is: -1 if compression disabled, otherwise it's the number
 *                of quicklistNodes to leave uncompressed at ends of quicklist.
 * 'fill' is the user-requested (or default) fill factor. */
typedef struct quicklist {
    //头结点
    quicklistNode *head; 
    //尾节点
    quicklistNode *tail; 
    //  quicklist中所有的压缩列表存储的entry数
    unsigned long count;  
    // quicklist的链表节点的数量
    unsigned int len; 
    // 负数代表级别,正数代表个数
    int fill : 16; 
    // 压缩级别
    unsigned int compress : 16; /* depth of end nodes not to compress;0=off *///压缩级别
} quicklist;
结构图示

quicklist的优化点

  • 对比于单纯的ziplist,quicklist可以减少数据插入带来的联动更新次数,因为一个节点内的ziplist不会存太多的元素
  • 对比于单纯的linkedlist,quicklist在单个node内部是ziplist的连续内存,节省空间和减少了内存碎片
    其实quicklist很像java中的HashMap的数组+链表的结构,综合了ziplist和linkedlist的有点,在使用场景上这种组合是结合了两个的优点的。

列表list的应用场景

  • 模拟消息队列,push和pop可以控制队列的进出顺序
posted @ 2020-04-03 00:31  南园故剑  阅读(2)  评论(0)    收藏  举报