Sorted Set (ZSet) 数据结构

  • Sorted Set (ZSet), 即有序集合, 底层使用 压缩列表(ziplist) 或者 跳跃表(skiplist)

    1. 使用 压缩列表(ziplist)

      当同时满足下面两个条件时,使用 ziplist 存储数据

      • 元素个数少于128个 (zset-max-ziplist-entries: 128)
      • 每个元素长度小于64字节 (zset-max-ziplist-value: 64)
    2. 不满足上面的条件, 使用 跳跃表(skiplist)
      • zset 在转为 skiplist 之后,即使元素被逐渐删除,也不会重新转为 ziplist
  • 有趣的命名: Sorted Set 为啥不缩写为 SSet ? GitHub有人提问

    • Z代表XYZ中的Z, 所以有排序的意思(这个说法有点牵强吧)
    • Set命令已经使用S作为前缀了, 所以Sorted Set不再使用S (可信度较高)
    • SSet 很奇怪, 很难发音 (这个理由也可以接受)

使用 ziplist 图解

使用 skiplist 图解

skiplist 定义

跳表是一种数据结构。它使得包含n个元素的有序序列的查找和插入操作的平均时间复杂度都是 O(logn),优于数组的 O(n)复杂度。快速的查询效果是通过维护一个多层次的链表实现的,且与下面一层链表元素的数量相比,每一层链表中的元素的数量更少。

skiplist 数据结构

//跳跃表节点
typedef struct zskiplistNode {
robj *obj; // 成员对象
double score; // 分值
struct zskiplistNode *backward; // 后退指针
// 层
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned int span; // 跨度
} level[];
} zskiplistNode; //跳跃表
typedef struct zskiplist {
struct zskiplistNode *header, *tail; // 表头节点和表尾节点
unsigned long length; // 表中节点的数量
int level; // 表中层数最大的节点的层数
} zskiplist; //有序集合
typedef struct zset {
dict *dict; // 字典,键为成员,值为分值, 用于支持 O(1) 复杂度的按成员取分值操作
zskiplist *zsl; // 跳跃表,按分值排序成员, 用于支持平均复杂度为 O(log N) 的按分值定位成员操作, 以及范围操作
} zset;

skiplist 图解

简单说下skiplist的查找过程:

比如查询 分数比 broadm 小的用户名

  1. 使用zset中的字典dict快速获取broadm节点对应的score=4
  2. 从header节点的最高层(第5层)出发,最高层(第5层)的前进节点是 obj:mike score:3,对比发现,此节点的score=3, 小于要查询的节点的score=4 (说明目标节点在此节点的右边), 应该继续前进, 但是此节点没有前进节点了, 那就降低一层,直到找到有前进节点的层为止(这里是第2层)
  3. 第2层的前进节点就是 broadm 了,找到了
  4. 因为skiplist是有序的,并且每个节点都保存了 backward 指针, 所以直接遍历链表就可以获取分数比broadm小的节点了

这里的数据量比较少,不容易看出来效果, 当数据量很大的时候,这种查询是非常高效的,平均时间复杂度为 O(logn),基本和平衡二叉树等效

Redis使用skiplist而不是红黑树的原因?

  • 红黑树实现细节过于复杂,比如为了保持平衡,需要做节点的旋转操作, 而skiplist完全是靠随机层数实现的自平衡,非常简单
  • 在范围查找时,跳跃表明显优于红黑树, 跳跃表是有序的链表,直接遍历后继节点即可, 而红黑树需要中序遍历,复杂度更高

Sorted Set (ZSet) 常用命令

  • ZADD key score member 添加一个或多个元素到集合中,如果已经存在,则更新其score
  • ZREM key member 删除集合中的指定元素
  • ZSCORE key member 获取集合中指定元素的score
  • ZRANK key member 获取集合中指定元素的排名(从0开始)
  • ZCARD key 获取集合中元素的个数
  • ZCOUNT key min max 统计score在闭区间[min,max]的元素的个数
  • ZRANGE key min max 获取指定排名范围内的元素
  • ZDIFF, ZINTER, ZUNION 求多个集合的 差集,交集,并集

Redis 原理 - Sorted Set (ZSet)的更多相关文章

  1. Redis原理及使用

    一:原理介绍 1:什么是redis?  Redis 是一个基于内存的高性能key-value数据库. 2:Reids的特点Redis本质上是一个Key-Value类型的内存数据库,很像memcache ...

  2. Redis原理与实践总结

    Redis原理与实践总结 本文主要对Redis的设计和实现原理做了一个介绍很总结,有些东西我也介绍的不是很详细准确,尽量在自己的理解范围内把一些知识点和关键性技术做一个描述.如有错误,还望见谅,欢迎指 ...

  3. Redis原理详解

    Redis原理详解 数据类型 Redis最为常用的数据类型主要有以下五种: String Hash List Set Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redi ...

  4. php使用redis的有序集合zset实现延迟队列

    延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息. 延迟队列的应用场景: 1.新用户注册,10分钟后发送邮件或站内信. 2.用户下单后,30分钟未支付,订单自动作废. 我 ...

  5. Redis原理篇

    Redis原理篇 1.发布 订阅模式 1.1列表 的局限 ​ 前面我们说通过队列的 rpush 和 lpop 可以实现消息队列(队尾进队头出),但是消费者需要不停地调用 lpop 查看 List 中是 ...

  6. Redis 系列(04-2)Redis原理 - 内存回收

    目录 Redis 系列(04-2)Redis原理 - 内存回收 Redis 系列目录 1. 过期策略 1.1 定时过期(主动淘汰) 1.2 惰性过期(被动淘汰) 1.3 定期过期 2. 淘汰策略 2. ...

  7. 面试被吊打系列 - Redis原理

    小张兴冲冲去面试,结果被面试官吊打! 小张: 面试官,你好.我是来参加面试的. 面试官: 你好,小张.我看了你的简历,熟练掌握Redis,那么我就随便问你几个Redis相关的问题吧.首先我的问题是,R ...

  8. 聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里)

    redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的.B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试) 还有个几个姊妹篇:介绍 ...

  9. Redis详细讲解(Redis原理,Redis安装,Redis配置,Redis使用,Redis命令)

    一.Redis介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发 ...

  10. Redis原理(一)

    基础和应用 1.Redis是远程调用技术的首字母缩写. 2.Redis可以用来做什么? Redis可以用来做缓存. 分布式锁 3.Redis的应用举例 记录帖子的点赞数.评论数和点击数.(使用HASH ...

随机推荐

  1. 即时通讯技术文集(第13期):Web端即时通讯技术精华合集 [共15篇]

    为了更好地分类阅读52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第13 期. [- 1 -] 新手入门贴:史上最全Web端即时通讯技术原理详解 [链接] http ...

  2. kubernetes系列(七) - Pod生命周期

    目录 1. pod生命周期 2. initC 2.1 initC介绍 2.2 initC的作用 2.3 initC的模版 2.4 initC的一些其他补充 3. Pod健康性检查(liveiness) ...

  3. DVWA靶场Weak Session IDs(弱会话) 漏洞所有级别通关教程及源码审计

    Weak Session IDs(弱会话) Weak Session IDs(弱会话ID)漏洞是一种安全漏洞,涉及在 web 应用程序中使用不安全或容易被猜测的会话标识符(Session IDs).会 ...

  4. [软件工具使用记录] windows离线ollama部署本地模型并配置continue实现离线代码补全

    qwen2.5coder发布之后,觉得差不多可以实现离线模型辅助编程了,所以尝试在公司内网部署模型,配合vsocde插件continue实现代码提示.聊天功能. 目前使用qwen2.5coder的32 ...

  5. ofd文件拆分合并思路探索 -- 附下载程序

      前言  ofd文件拆分合并会在多个场合用到,但市面上此类工具并不多.拆分和合并虽然为两个功能,但从编程角度考虑,其处理思路有相同之处.文章就以合并为例,讲一下处理思路.作者也写了一个拆分合并小工具 ...

  6. 对比使用DeepSeek与文新一言,了解DeepSeek的关键技术论文

    DeepSeek是国内大模型技术的新秀,最近也在业界和媒体界火爆出圈,所以想学习一下其技术. 大模型时代,学习知识,当然首先想到利用大模型,由于在过去一年,对DeepSeek使用不多,所以想和文新一言 ...

  7. java集合中的迭代器Iterator和数组内置方法以及常见的报错

    删除Map的中某一项报错 package part; import java.util.HashMap; import java.util.Set; public class Java01 { pub ...

  8. Git操作的基本命令

    git命令常用步骤 初始化,把当前文件夹作为git本地仓库 git init 把本地仓库与选程仓库关联 git remote add origin http://gitee.com/ 把项目区中做了修 ...

  9. SqlServer性能检测之Sql语句排查

    很多时候,我们在用SQL语句查询数据时,难免会漏掉对SQL语句性能的考虑,所以有时就会造成SqlServer服务占用过高的问题,为了大致排查是哪些SQL语句造成的问题,我们可以通过如下SQL查询出最近 ...

  10. mac支持rar解压缩

    一.下载 下载macOS版本:RAR 5.71 for macOS (64 bit) 二.安装 1.双击解压刚才下载的rarosx-5.7.1.tar,使用终端进入刚才解压的文件夹目录下cd /Use ...