Redis常规指令及跳表

第一部分:Redis 常规指令

Redis 是一个键值存储系统,其指令通常以 COMMAND KEY_NAME [ARGUMENTS...] 的形式存在。下面我们按照数据结构和功能来分类。

1. 全局/键操作指令

这些指令不特定于某一数据类型,适用于所有键。

指令描述示例
KEYS pattern查找所有符合给定模式(pattern)的键。(生产环境慎用,会阻塞)KEYS user:*
EXISTS key检查键是否存在。EXISTS mykey
TYPE key返回键所存储的值的类型。TYPE mylist
DEL key [key ...]删除一个或多个键。DEL key1 key2
EXPIRE key seconds为键设置过期时间(单位:秒)。EXPIRE session:123 3600
TTL key返回键的剩余生存时间。TTL session:123
RENAME key newkey重命名键。RENAME oldkey newkey
2. 字符串

String 是 Redis 最基本的数据类型,可以存储文本、JSON、序列化对象,甚至是二进制数据(如图片)。

指令描述示例
SET key value设置键的值。SET name "Alice"
GET key获取键的值。GET name
SETEX key seconds value设置键的值和过期时间(原子操作)。SETEX cache:page1 60 "..."
SETNX key value只有键不存在时,才设置键的值(分布式锁常用)。SETNX lock:myjob 1
INCR key将键中存储的数字值增一。INCR counter
DECR key将键中存储的数字值减一。DECR counter
INCRBY key increment将键中存储的数字值增加指定的增量。INCRBY counter 10
APPEND key value将指定值追加到键的原始值末尾。APPEND greeting " World!"
3. 哈希

Hash 是一个键值对集合,特别适合存储对象信息。例如,一个用户对象。

指令描述示例
HSET key field value设置哈希表 key 中的字段 field 的值。HSET user:1001 name "Bob" age 30
HGET key field获取哈希表 key 中给定字段 field 的值。HGET user:1001 name
HGETALL key获取在哈希表 key 中的所有字段和值。HGETALL user:1001
HDEL key field [field ...]删除哈希表 key 中的一个或多个指定字段。HDEL user:1001 age
HEXISTS key field查看哈希表 key 中,指定的字段是否存在。HEXISTS user:1001 email
HINCRBY key field increment为哈希表 key 中的字段 field 的值加上增量 increment。HINCRBY user:1001 score 5
4. 列表

List 是一个字符串元素的有序集合,按插入顺序排序。底层是双向链表或快速列表(ziplist/quicklist)。

指令描述示例
LPUSH key value [value ...]将一个或多个值插入到列表头部。LPUSH mylist "world" "hello"
RPUSH key value [value ...]将一个或多个值插入到列表尾部。RPUSH mylist "redis"
LPOP key移除并返回列表头部元素。LPOP mylist
RPOP key移除并返回列表尾部元素。RPOP mylist
LLEN key获取列表长度。LLEN mylist
LRANGE key start stop获取列表指定范围内的元素(0表示第一个,-1表示最后一个)。LRANGE mylist 0 -1
LINDEX key index通过索引获取列表中的元素。LINDEX mylist 0
5. 集合

Set 是一个无序、唯一的字符串元素集合。常用于标签、共同好友等场景。

指令描述示例
SADD key member [member ...]向集合添加一个或多个成员。SADD mytags "redis" "database" "nosql"
SMEMBERS key返回集合中的所有成员。SMEMBERS mytags
SISMEMBER key member判断成员元素是否是集合的成员。SISMEMBER mytags "redis"
SREM key member [member ...]移除集合中一个或多个成员。SREM mytags "nosql"
SCARD key获取集合的成员数。SCARD mytags
SINTER key [key ...]返回给定所有集合的交集。SINTER set1 set2
SUNION key [key ...]返回给定所有集合的并集。SUNION set1 set2
SDIFF key [key ...]返回给定所有集合的差集。SDIFF set1 set2
6. 有序集合

这是跳表的核心应用场景。Sorted Set 和 Set 一样,也是元素唯一的集合。但每个元素都会关联一个 double 类型的分数。Redis 正是通过这个分数来为集合中的成员进行从小到大的排序。

指令描述示例
ZADD key score member [score member ...]向有序集合添加一个或多个成员,或更新已存在成员的分数。ZADD leaderboard 100 "player1" 200 "player2"
ZRANGE key start stop [WITHSCORES]通过索引区间返回有序集合中指定区间内的成员(分数从低到高)。ZRANGE leaderboard 0 -1 WITHSCORES
ZREVRANGE key start stop [WITHSCORES]通过索引区间返回有序集合中指定区间内的成员(分数从高到低)。ZREVRANGE leaderboard 0 2
ZRANK key member返回有序集合中指定成员的排名(分数从低到高排序)。ZRANK leaderboard "player2"
ZREVRANK key member返回有序集合中指定成员的排名(分数从高到低排序)。ZREVRANK leaderboard "player2"
ZSCORE key member返回有序集合中指定成员的分数值。ZSCORE leaderboard "player1"
ZREM key member [member ...]移除有序集合中的一个或多个成员。ZREM leaderboard "player1"
ZCARD key获取有序集合的成员数。ZCARD leaderboard
ZCOUNT key min max计算在有序集合中指定区间分数的成员数。ZCOUNT leaderboard 0 150

第二部分:跳表

1. 什么是跳表?

跳表是一种概率平衡的数据结构,可以看作是带有“快速通道”的有序链表。它通过在原始有序链表之上建立多级索引,来实现快速的查找、插入和删除操作,其平均时间复杂度为 O(log N),最坏情况为 O(N)。

为什么需要跳表?

  • 普通有序链表的查找效率是 O(N),因为必须从头开始逐个遍历。
  • 平衡二叉树(如红黑树)虽然能实现 O(log N) 的查找,但实现复杂,且在并发环境下需要复杂的锁机制来保证平衡。
  • 跳表提供了一种在实现上比平衡树更简单,且性能与之媲美的方案。
2. 跳表的底层原理

让我们通过一个例子来理解跳表是如何工作的。

第0步:原始有序链表
假设我们有一个有序链表:1 <-> 7 <-> 20 <-> 35 <-> 50 <-> 80
如果要查找 35,我们需要从头节点 1 开始,依次比较 720,最后找到 35,共比较3次。

1 -> 7 -> 20 -> 35 -> 50 -> 80

第1步:建立一级索引(“快车道”)
我们从链表中抽取部分节点(例如,每隔一个节点)组成一个新的一级索引链表。

  • 索引层:1 -> 20 -> 50
  • 原始层:1 -> 7 -> 20 -> 35 -> 50 -> 80

现在查找 35

  1. 从索引层 1 开始,比较 2035 > 20,继续在索引层找。
  2. 找到 5035 < 50,说明 35 在 20 和 50 之间。
  3. 从索引层的 20 节点下降到原始层的 20 节点。
  4. 在原始层从 20 开始向后遍历,立刻找到 35

这次我们只比较了 205035,共3次。虽然在这个小例子中优势不明显,但当数据量巨大时,效率提升是惊人的。

第2步:建立多级索引
我们可以在一级索引的基础上,再抽取部分节点建立二级索引。

  • 二级索引:1 -> 50
  • 一级索引:1 -> 20 -> 50
  • 原始层:1 -> 7 -> 20 -> 35 -> 50 -> 80

现在查找 35

  1. 从二级索引 1 开始,比较 5035 < 50
  2. 从二级索引的 1 节点下降到一级索引的 1 节点。
  3. 在一级索引从 1 开始,比较 2035 > 20,继续找。
  4. 找到 5035 < 50
  5. 从一级索引的 20 节点下降到原始层的 20 节点。
  6. 在原始层找到 35

比较次数依然是 502035。但想象一下,如果链表有上百万个节点,多级索引可以让你“大步跨越”,迅速缩小查找范围。

如何保持平衡?
跳表不像平衡树那样有严格的旋转规则。它通过随机函数来决定一个节点应该被提升到多少级索引。

  • 当一个新节点插入时,会调用一个随机函数(例如,抛硬币)。
  • 如果结果是“正面”,就将该节点提升到一级索引。
  • 再次抛硬币,如果是“正面”,就提升到二级索引。
  • …直到出现“反面”为止。

这种随机化的方法使得跳表在宏观上保持平衡,避免了最坏情况,同时实现非常简单。

3. 为什么 Redis 选择使用跳表?

在 Redis 中,Sorted Set(ZSET)需要同时满足两个核心需求:

  1. 能按分数(score)进行排序
  2. 能快速进行范围查找(例如,查找分数在 100 到 200 之间的所有成员)。

Redis 在实现 ZSET 时,实际上使用了两种数据结构:

  • 哈希表:用于存储 member 到 score 的映射。这使得 ZSCORE 操作的时间复杂度为 O(1)
  • 跳表:按 score 排序存储所有 member 和 score

选择跳表而不是平衡树(如红黑树)的原因主要有以下几点:

  1. 实现简单:跳表的实现逻辑远比红黑树等平衡树要简单、直观。Redis 的作者 Salvatore Sanfilippo 曾表示,他选择跳表就是因为代码更容易写、更不容易出错。
  2. 范围查找性能优异:跳表本身就是基于链表的,进行范围操作(如 ZRANGE)非常自然和高效。只需找到范围的起始点,然后沿着链表顺序遍历即可。平衡树的范围查找需要通过中序遍历,虽然也是 O(log N + M),但实现上跳表更直接。
  3. 内存占用:跳表通过随机化建立索引,其平均空间复杂度为 O(N),与平衡树相当。但在实践中,通过调整概率参数(如 Redis 中 p=0.25),可以很好地控制内存使用。
  4. 并发友好:跳表的修改操作(插入、删除)通常只影响局部节点,而平衡树的旋转操作可能影响较大范围的子树,这使得跳表在并发环境下(虽然 Redis 是单线程模型,但设计理念上)更容易实现无锁或细粒度锁。
4. 跳表在 Redis 中的应用

跳表是 Redis 中 Sorted Set (ZSET) 的核心数据结构。

  • ZADD:插入一个新元素时,Redis 会先通过哈希表检查 member 是否已存在。如果存在,则更新其 score 并在跳表中调整位置;如果不存在,则创建新节点,并通过随机算法决定其索引层数,然后将其插入到跳表的相应位置。时间复杂度平均为 O(log N)
  • ZRANGE / ZREVRANGE:通过跳表快速定位到范围的起始节点,然后沿着 prev 或 next 指针顺序遍历,直到范围的结束节点。时间复杂度为 O(log N + M),其中 N 是 ZSET 的元素总数,M 是返回的元素个数。
  • ZRANK / ZREVRANK:查找某个 member 的排名。跳表需要维护一个 span(跨度)属性,表示当前指针指向的下一个节点之间,在原始链表中有多少个节点。通过累加 span,可以快速计算出排名。时间复杂度为 O(log N)
  • ZREM:删除一个元素,需要从哈希表和跳表中同时删除。在跳表中删除一个节点后,需要更新其上层所有索引中指向它的指针。时间复杂度平均为 O(log N)

总结

  • Redis 常规指令是操作 Redis 的基础,理解不同数据类型(String, Hash, List, Set, Sorted Set)及其对应指令是使用 Redis 的前提。
  • 跳表是一种高效且实现相对简单的有序数据结构。Redis 在 Sorted Set 中巧妙地结合了哈希表跳表,哈希表负责 O(1) 的单点查找,跳表负责 O(log N) 的排序和范围操作,这使得 Sorted Set 成为了 Redis 中功能最强大、最常用的数据结构之一。选择跳表而非平衡树,体现了 Redis 追求简洁、高效和可靠的设计理念。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/2839.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

指纹云手机×Snapchat Spotlight:动态GPS+陀螺仪仿生方案

——基于时空坐标系重构与生物运动模拟的AR营销突破​​一、Snapchat Spotlight广告的技术困局​设备指纹关联风险​Snapchat通过陀螺仪基线值&#xff08;0.1误差&#xff09;和GPS坐标&#xff08;精度&#xff1c;5米&#xff09;构建设备指纹&#xff0c;相似度&#xff1e…

Java 编辑器与 IDE:开发者手中的利剑与盾牌

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C基础知识知识强化补充、C/C干货分享&学习过程记录 &#x1f349;学习方向&#xff1a;C/C方向学习者…

不再让Windows更新!Edge游戏助手卸载及关闭自动更新

文章目录Windows系统更新问题方法一&#xff1a;通过注册表手动设置1. 打开注册表编辑器2. 定位到目标路径3. 创建新的DWORD值4. 修改数值方法二&#xff1a;命令行设置1. 打开命令提示符2. 输入命令验证设置是否生效恢复更新Edge关闭游戏助手Edge关闭后台运行Edge关闭自动更新…

从Android到鸿蒙:一场本应无缝的转型-优雅草卓伊凡

从Android到鸿蒙&#xff1a;一场本应无缝的转型-优雅草卓伊凡看到Android开发者询问如何转向鸿蒙&#xff0c;卓伊凡不禁摇头&#xff1a;真正的Android工程师根本不需要“学习”鸿蒙&#xff0c;只需要简单查阅文档即可。近年来&#xff0c;随着鸿蒙系统的不断发展&#xff0…

Linux的线程概念与控制

目录 1、Linux的线程概念 1.1 什么是线程 1.2 分页式存储管理 1.3 线程的优点 1.4 线程的缺点 3、Linux的线程控制 3.1 POSIX线程库 3.2 线程创建 3.3 线程退出 3.4 线程等待 3.5 线程分离 1、Linux的线程概念 1.1 什么是线程 首先Linux内核不区分"进程"…

云原生俱乐部-RH294知识点归纳(3)

其实ansible还剩下使用角色和ansible内容集合来简化playbook、对ansible进行故障排除和自动执行Linux管理任务三部分。至于如何对ansible进行故障排除&#xff0c;只有在生产中碰到了故障才用得上&#xff0c;并且即使碰上的还是需要具体问题具体分析&#xff0c;但是可以该部分…

Flink 实时加购数据“维表补全”实战:从 Kafka 到 HBase 再到 Redis 的完整链路

一、业务背景 在电商实时运营场景中&#xff0c;加购行为&#xff08;AddShoppingCart&#xff09; 是最核心的用户行为之一&#xff0c;每秒钟可能产生数万条加购事件。以某头部电商平台为例&#xff0c;大促期间加购QPS可突破50万。 为了支持实时推荐、实时营销、实时大屏等业…

【数据结构】二叉树的顺序存储、堆的实现及其应用:堆排序与Top-K问题

二叉树的顺序存储、堆的实现及其应用&#xff1a;堆排序与Top-K问题 ✨前言&#xff1a;在上一节【树与二叉树】中&#xff0c;我们已经了解了二叉树的基本结构与存储方式。 本篇文章将更进一步&#xff0c;重点介绍 二叉树的顺序结构&#xff0c;并在此基础上引出一个重要的数…

SpringBoot 快速上手:从环境搭建到 HelloWorld 实战

在 Java 开发领域&#xff0c;Spring 框架占据着举足轻重的地位&#xff0c;但它复杂的配置曾让不少开发者望而却步。SpringBoot 的出现&#xff0c;如同为 Spring 框架装上了 “加速器”&#xff0c;以 “约定大于配置” 的理念简化了开发流程。本文将从环境准备、Maven 配置入…

一键部署开源 Coze Studio

文章目录一、简介1、什么是 Coze Studio2、参考地址二、安装部署1、安装docker2、安装git3、下载core4、配置公网可用5、登录成功一、简介 1、什么是 Coze Studio Coze Studio 是一站式 AI Agent 开发工具。提供各类最新大模型和工具、多种开发模式和框架&#xff0c;从开发到…

墨刀原型设计工具操作使用指南及实践操作

壹、墨刀原型设计工具操作使用指南 一、基础入门 1. 软件版本与环境要求 版本区别&#xff1a; 免费版&#xff1a;支持 3 个项目&#xff0c;单项目最多 20 页&#xff0c;基础组件与交互&#xff0c;团队成员≤5 人&#xff1b;专业版&#xff08;付费&#xff09;&#x…

博士招生 | 美国圣地亚哥州立大学 Yifan Zhang 课题组博士招生,AI 安全领域顶尖平台等你加入!

内容源自“图灵学术博研社”gongzhonghao学校简介圣地亚哥州立大学&#xff08;San Diego State University, SDSU&#xff09;是美国加州南部久负盛名的公立研究型大学。学校坐落于科技产业高度活跃的南加州地区&#xff0c;与本地软件、电信、生物科技、国防及清洁能源等领域…