Redis Zset(有序集合)底层实现原理解析

Redis Zset(有序集合)底层实现原理解析

在 Redis 中,Zset(Sorted Set,有序集合)是一种结合了哈希表和跳表的数据结构,它不仅支持快速的插入、删除和查找操作,还能高效地实现范围查询和排序操作。本文将详细介绍 Zset 的底层实现原理。

1. Zset 结构概述

Zset 主要由两个数据结构组成:

  • 跳表(skiplist):用于高效的范围查询和排序。
  • 字典(hash table):用于快速查找特定元素的分数。

这两个数据结构相互配合,使得 Zset 既能快速查找元素分数,又能高效地按分数排序访问数据。

2. 跳表(Skiplist)—— 高效的排序结构

跳表是一种 多层级链表结构,用于有序数据存储,支持 O(log N) 级别的插入、删除、查找 操作。

2.1 跳表的结构

跳表的基本结构如下:

  • 多个层级(levels),每一层都是一个升序链表。
  • 底层(level 1)包含所有元素,越高层的链表元素越少。
  • 元素被随机分配到不同层,插入时按一定概率决定元素的层数(Redis 采用 1/4 的概率)。

2.2 跳表的查找过程

  1. 从最高层开始,查找比目标值小但最接近的元素。
  2. 若当前层无更大元素,则下降到下一层继续查找。
  3. 直到底层链表找到目标值或确认目标值不存在。

2.3 跳表的插入过程

  1. 先在跳表中查找插入位置。
  2. 通过随机算法决定新元素的层数。
  3. 在对应层级插入新元素,并维护链表指针。

2.4 跳表的删除过程

  1. 先查找目标元素。
  2. 遍历所有包含该元素的层级,移除其节点。
  3. 若删除后某些层变为空,则删除该层。

3. 哈希表(Hash Table)—— 快速查找分数

除了跳表,Redis 还使用 哈希表(dict) 存储 Zset 元素与分数的映射关系,使得 通过成员名快速查询分数 变得高效(O(1) 复杂度)。

3.1 哈希表的作用

  • 通过 key(成员名) 快速找到 score(分数)
  • 通过 成员名获取分数,然后去跳表中查找排名或范围。

3.2 为什么需要哈希表?

  • 跳表按分数排序,但无法快速按 成员名 查找分数。
  • 哈希表提供 O(1) 级别的 成员名 -> 分数 查询能力。

4. Zset 如何存储数据?

在 Redis 代码实现中,Zset 主要由 zset 结构体 组织,底层存储分两种方式:

  1. ziplist(压缩列表):元素少时使用
  2. skiplist(跳表)+ dict(哈希表):元素多时使用

4.1 Ziplist 模式(小数据量时)

  • 适用于 成员数量 < 128 且 每个成员+分数 < 64 字节
  • 使用 连续内存存储,节省空间,但插入、查找性能较差。

4.2 Skiplist + Dict 模式(大数据量时)

  • 适用于 大规模数据,当 Zset 变大时自动转换为此结构。
  • 跳表 用于 按分数排序字典 用于 O(1) 级查找

5. Zset 典型操作及复杂度

操作命令时间复杂度
添加元素ZADD key score memberO(log N)
删除元素ZREM key memberO(log N)
获取元素排名ZRANK key memberO(log N)
获取分数范围元素ZRANGEBYSCORE key min maxO(log N + M)
获取指定排名元素ZRANGE key start stopO(log N + M)

6. 总结

  • 小数据量时,Zset 使用 ziplist(压缩列表) 存储,节省空间但性能较低。
  • 大数据量时,Zset 使用 skiplist + dict 组合,保证查询效率。
  • 跳表用于排序操作,提供 O(log N) 级效率。
  • 哈希表用于成员分数查找,提供 O(1) 级效率。
  • Zset 适用于排行榜、权重排序、时间序列等应用场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值