返回
Redis源码剖析之Sorted Set有序集合
后端
2024-02-05 06:10:55
Sorted Set 简介
Sorted Set 是一种有序集合,集合中的元素被分配了一个分数,并且元素按照分数的升序排列。Sorted Set 的特点是:
- 元素是唯一的,即集合中不会出现重复的元素。
- 元素可以被更新,但不能被删除。
- 元素的分数可以被更新。
- Sorted Set 支持快速查找、插入和删除操作,时间复杂度为 O(log n)。
Sorted Set 实现原理
Sorted Set 在 Redis 中是通过跳表(skip list)来实现的。跳表是一种随机化的数据结构,它将元素存储在多个层次中,每一层都有不同的概率被选择。这使得查找、插入和删除操作的时间复杂度都为 O(log n)。
跳表节点的结构定义如下:
typedef struct redisSkiplistNode {
double score;
robj *obj;
struct redisSkiplistNode *backward;
struct redisSkiplistLevel {
unsigned long span;
struct redisSkiplistNode *forward;
} level[];
} redisSkiplistNode;
跳表可以被看作是一个有序链表的集合,其中每个链表都存储着不同分数的元素。链表之间的连接通过一个随机数来决定。
跳表的定义如下:
typedef struct redisSkiplist {
struct redisSkiplistNode *header, *tail;
unsigned int length;
int level;
} redisSkiplist;
跳表节点查询的过程如下:
redisSkiplistNode *redisSkiplistFind(redisSkiplist *skiplist, double score) {
redisSkiplistNode *node = skiplist->header;
int i = skiplist->level - 1;
while (i >= 0) {
while (node->level[i].forward &&
node->level[i].forward->score < score) {
node = node->level[i].forward;
}
i--;
}
return node;
}
层数设置是跳表的关键,它决定了跳表的性能。层数越多,跳表的查找、插入和删除操作就越快,但同时跳表的内存占用也会越大。Redis 中的 Sorted Set 使用了自适应层数设置算法,它可以根据 Sorted Set 的大小自动调整层数。
跳表插入节点的过程如下:
void redisSkiplistInsert(redisSkiplist *skiplist, double score, robj *obj) {
redisSkiplistNode *new_node = zslCreateNode(score, obj, NULL);
redisSkiplistNode *update[REDIS_SKIPLIST_MAX_LEVEL];
unsigned int rank[REDIS_SKIPLIST_MAX_LEVEL];
int i, level;
redisSkiplistNode *node = skiplist->header;
for (i = skiplist->level - 1; i >= 0; i--) {
while (node->level[i].forward &&
node->level[i].forward->score < score) {
rank[i] += node->level[i].span;
node = node->level[i].forward;
}
update[i] = node;
}
level = redisGetRandomLevel();
if (level > skiplist->level) {
for (i = skiplist->level; i < level; i++) {
update[i] = skiplist->header;
rank[i] = 0;
skiplist->level++;
}
}
for (i = 0; i < level; i++) {
new_node->level[i].span = skiplist->length - rank[i];
new_node->level[i].forward = update[i]->level[i].forward;
update[i]->level[i].forward = new_node;
}
skiplist->length++;
}
总结
Sorted Set 是 Redis 中一种非常重要的数据结构,它具有快速查找、插入和删除操作的特点。Sorted Set 在 Redis 中是通过跳表来实现的,跳表是一种随机化的数据结构,它将元素存储在多个层次中,每一层都有不同的概率被选择。这使得查找、插入和删除操作的时间复杂度都为 O(log n)。