ZSet详解

[toc]

ZSet - Sorted Set,每一个元素必须指定score值和member值,集合内的元素实际值为member,并按照score值排序。

  • member必须唯一(相当于key)
  • 按照score值排序
  • 可以根据member查询score

可以看出,ZSet的特点是键值对存储(member - score对)、键唯一、可排序,因此采用了Dict(HT)编码 + SkipList的结构

  • SkipList跳表满足键值存储和可排序,但实现满足键唯一、以及根据member查询score困难
  • Dict(HT)是键值对存储、满足键唯一,但不可排序。

由于编码只能写一个,Redis中ZSet的encoding是SkipList

1
2
3
4
5
// server.h
typedef struct zset {
dict *dict;
zskiplist *zsl;
} zset;

image-20240922145225898

可以看出,ZSet是一个很消耗内存的数据类型,因此在数据量不多时,ZSet会采用ZipList(Redis6)或Listpack(Redis7)结构来节约内存。

  • 需要元素数量小于zset_max_ziplist_entries且每个元素都小于zset_max_ziplist_value (Redis6, 7类似)

  • 当不满足条件时会自动进行编码转换

ZipList和Listpack本身没有排序功能,且没有键值对的概念,因此需要其他代码辅助实现功能。

  • ZipList是连续内存,因此element和score值存储为两个相邻的entry,element在前,score在后。
  • score越小越接近队首,按照score值升序排列。

image-20240922150726316