Redis学习小计(5) - 基本数据类型:列表(list)

Redis基本数据类型:列表(list)

  Redis内部使用两种结构实现list:

  • 压缩列表(ziplist)
  • 快速列表(quicklist)

1. 压缩列表(ziplist)

  当列表存储的是整数或者很短的字符串时,Redis内部会优先使用ziplist。
  使用这种结构时,redisObject.encoding = OBJ_ENCODING_ZIPLIST
  ziplist是由三部分组成,header + entries + end

  • ziplist header
      ziplist head 是由两个unsigned int 和一个unsigned short组成,占用10Byte。其中第一个unsigned int存储ziplist占用的所有内存,第二个unsigned int存储列表尾部节点距离起始位置的偏移量,最后一个unsigned short记录的是节点数量,定义如下:

#define ZIPLIST_HEADER_SIZE (sizeof(uint32_t)2+sizeof(uint16_t))
#define ZIPLIST_BYTES(zl) (
((uint32_t*)(zl)))
#define ZIPLIST_TAIL_OFFSET(zl) (((uint32_t)((zl)+sizeof(uint32_t))))
#define ZIPLIST_LENGTH(zl) (((uint16_t)((zl)+sizeof(uint32_t)*2)))

  • ziplist entries
      ziplist entries是一段连续的内存空间,所以我们可以把他当成数组来访问。
      zlentry用于记录每个节点的信息,结构如下:

typedef struct zlentry {
  unsigned int prevrawlensize;
  unsigned int prevrawlen;
  unsigned int lensize;
  unsigned int len;
  unsigned int headersize;
  unsigned char encoding;
  unsigned char *p;
} zlentry;

  ziplist内部还定义了两个指针,一个指向第一个entry,一个指向最后一个entry,这样就把lpush和rpush的时间复杂度都降到了O(1),定义如下:

#define ZIPLIST_ENTRY_HEAD(zl) ((zl)+ZIPLIST_HEADER_SIZE)
#define ZIPLIST_ENTRY_TAIL(zl) ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))

  • ziplist end
      ziplist end是一个固定的标示符255,占用1Byte

#define ZIPLIST_ENTRY_END(zl) ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)


2. 快速列表(quicklist)

  使用这种结构时,redisObject.encoding = OBJ_ENCODING_QUICKLIST
  quicklist的定义如下:

typedef struct quicklist {
  quicklistNode *head;
  quicklistNode *tail;
  unsigned long count;
  unsigned long len;
  int fill : 16;
  unsigned int compress : 16;
} quicklist;

typedef struct quicklistNode {
  struct quicklistNode *prev;
  struct quicklistNode *next;
  unsigned char *zl;
  unsigned int sz;
  unsigned int count : 16;
  unsigned int encoding : 2;
  unsigned int container : 2;
  unsigned int recompress : 1;
  unsigned int attempted_compress : 1;
  unsigned int extra : 10;
} quicklistNode;

  quicklistNode采用的是双向链表进行索引,为了节省空间,每一个node里面存储的时一个ziplist(zl).当每个ziplist大小超过8K时,才会重新创建一个新的quicklistNode。

#define SIZE_SAFETY_LIMIT 8192
if (_quicklistNodeAllowInsert(…)) {
  ziplistPush(…);
} else {
  quicklistNode *node = quicklistCreateNode();
  ziplistPust(…);
}


3. command

  • BLPOP - Remove and get the first element in a list, or block until one is available
  • BRPOP - Remove and get the last element in a list, or block until one is available
  • BRPOPLPUSH - Pop a value from a list, push it to another list and return it; or block until one is available"
  • LINDEX - Get an element from a list by its index
  • LINSERT - Insert an element before or after another element in a list
  • LLEN - Get the length of a list
  • LPOP - Remove and get the first element in a list
  • LPUSH - Prepend one or multiple values to a list
  • LPUSHX - Prepend a value to a list, only if the list exists
  • LRANGE - Get a range of elements from a list
  • LREM - Remove elements from a list
  • LSET - Set the value of an element in a list by its index
  • LTRIM - Trim a list to the specified range
  • RPOP - Remove and get the last element in a list
  • RPOPLPUSH - Remove the last element in a list, prepend it to another list and return it
  • RPUSH - Append one or multiple values to a list
  • RPUSHX - Append a value to a list, only if the list exists

上一篇:Redis学习小计(4) - 基本数据类型:字符串(string)
下一篇:Redis学习小计(6) - 基本数据类型:哈希(hash)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值