Redis ZSet底层结构与插入元素的过程
Redis Zset由哈希表和跳表构成。哈希表记录了member与score的映射,可以快速查询member的score;跳表有序存储元素,用于范围查询。
跳表的实现原理
跳表简单来说是一个多层链表。Redis的跳表有一个链表组成,每个节点内部包含元素值、score、后退指针和level数组,level数组记录了多层索引。
typedef struct zskiplistNode {
//Zset 对象的元素值
sds ele;
//元素权重值
double score;
//后退指针
struct zskiplistNode *backward;
//节点的level数组,保存每层上的前向指针和跨度
struct zskiplistLevel {
struct zskiplistNode *forward;
unsigned long span;
} level[];
} zskiplistNode;
跳表的形态如图。每个大方框代表一个zskiplistNode,蓝色的方框代表level数组,level数组指向了下一个zskiplistNode节点。

插入元素的过程
-
搜索元素插入的位置
redis会记录每层能够达到的最右的节点,用数组update记录。
算法会for循环从上到下遍历。指针x首先从最高层节点出发。如果右边节点不为空且score小于给定值,则x右移直到右边的节点为空或者score大于给定值,此时会将当前的x的指针记录到数组中。后续遍历不用从头开始,直接从x的位置继续查找下一层。最终得到每一层能够达到的最右的节点。
比如:
插入元素9,前五层能够达到的最右边的节点为5、8、8.5、8.5、8.5 -
计算一个随机的层数
Redis为当前元素随机分配一个层数,比如4层。 -
插入并更新span
插入时,根据数组中的记录,将每一层节点的对应的level的forward指针指向新插入的节点,沿途还会更新每个节点的span。update[0]指向9,而9的backward指向update[0]对应的节点。


浙公网安备 33010602011771号