文章目录
- [第一章 Redis 通用命令](#第一章 Redis 通用命令)
-
- [1.Redis 命令交互基础](#1.Redis 命令交互基础)
-
- [1.1 redis-cli 与 Redis 服务](#1.1 redis-cli 与 Redis 服务)
- [1.2 SET 与 GET](#1.2 SET 与 GET)
- [2.Redis 通用命令](#2.Redis 通用命令)
-
- [2.1 KEYS:按照模式查找 key](#2.1 KEYS:按照模式查找 key)
- [2.2 EXISTS:判断 key 是否存在](#2.2 EXISTS:判断 key 是否存在)
- [2.3 DEL:删除指定 key](#2.3 DEL:删除指定 key)
- [2.4 EXPIRE、PEXPIRE:设置 key 的生命周期](#2.4 EXPIRE、PEXPIRE:设置 key 的生命周期)
- [补充:Redis 一个 key 只有一个过期时间,EXPIRE 和 PEXPIRE 本质都是修改这个过期时间,因此后设置的会覆盖先设置的,不会累加。](#补充:Redis 一个 key 只有一个过期时间,EXPIRE 和 PEXPIRE 本质都是修改这个过期时间,因此后设置的会覆盖先设置的,不会累加。)
- [2.5 TTL、PTTL:查询剩余生命周期](#2.5 TTL、PTTL:查询剩余生命周期)
- [3.Redis 过期 key 的实现思路](#3.Redis 过期 key 的实现思路)
-
- [3.1 定期删除与惰性删除](#3.1 定期删除与惰性删除)
- [3.2 为什么不为每个 key 创建一个定时器](#3.2 为什么不为每个 key 创建一个定时器)
- [3.3 基于优先级队列的定时器](#3.3 基于优先级队列的定时器)
- [3.4 时间轮](#3.4 时间轮)
- [3.5 Redis 的事件循环](#3.5 Redis 的事件循环)
- [4.TYPE:查询 value 的数据类型](#4.TYPE:查询 value 的数据类型)
- [5.Redis 通用命令总结](#5.Redis 通用命令总结)
第一章 Redis 通用命令
Redis 的数据最终都以 key-value 的形式组织。无论 value 使用 String、List、Set、Hash、ZSet 还是 Stream,访问数据时都需要先定位 key,因此 Redis 提供了一组与具体 value 类型无关的通用命令,用于完成 key 的查找、存在性判断、删除、过期时间设置以及类型查询等操作。在学习这些命令之前,需要先理解 Redis 命令的执行方式以及最基本的键值模型。
Redis 命令大小写不敏感;Redis 存储的数据大小写敏感。字符串可以不加引号,也可以使用单引号或双引号表示,但引号只是客户端解析参数的方式,不会作为实际数据保存。只有字符串包含空格等特殊字符时SET name "hello world",通常才需要加引号。
Redis 内部通过 哈希表(dict)存储 key
1.Redis 命令交互基础
1.1 redis-cli 与 Redis 服务
Redis 采用客户端与服务器结构。redis-server 负责保存和处理数据,redis-cli 则是 Redis 自带的命令行客户端。进入 redis-cli 后输入的命令,会由客户端发送给 Redis 服务器执行,再将服务器返回的结果显示出来。
bash
redis-cli
连接本机默认 Redis 服务后,会看到类似下面的提示符:
bash
127.0.0.1:6379>

其中 127.0.0.1 表示当前连接的 Redis 服务器地址,6379 是 Redis 默认端口。之后输入的 SET、GET、KEYS、DEL 等命令,本质上都需要经过一次客户端与服务器之间的请求和响应。
Redis 的命令数量很多,没有必要依靠死记硬背掌握全部参数。实际使用时一方面需要熟悉高频命令,另一方面需要能够根据命令文档确认语法、参数、返回值以及时间复杂度。对于 Redis 这类基础组件而言,理解命令解决什么问题,比单纯记住命令名称更加重要。
1.2 SET 与 GET
理解 Redis 通用命令之前,可以先通过 SET 和 GET 建立最基本的键值模型。SET 用于写入一个 String 类型的键值对:

bash
SET key value
例如:
bash
127.0.0.1:6379> SET key1 value1
OK
127.0.0.1:6379> SET key2 value2
OK
Redis 中的 key 本质上都是字符串 。对于 SET 命令来说,value 同样按照字符串或字节序列进行存储,因此执行上述操作后,可以理解为 Redis 中形成了如下映射关系:
bash
key1 -> value1
key2 -> value2
GET 则根据 key 获取对应的 String value:
bash
127.0.0.1:6379> GET key1
"value1"
如果查询的 key 不存在,Redis 不会返回一个普通字符串,而是返回空值,在 redis-cli 中通常表现为 (nil):
bash
127.0.0.1:6379> GET not-exist
(nil)
这里的 (nil) 表示这个 key 没有对应的值 ,不要把它理解成字符串 "nil"。后续很多 Redis 命令都会涉及"不存在的 key",理解这一点非常重要。
2.Redis 通用命令
Redis 的 value 可以拥有不同的数据类型,而 key 的组织方式始终一致,因此有一部分命令并不关心 value 到底是 String、List 还是 Hash,只围绕 key 本身工作。这类命令就是 Redis 的通用命令。
2.1 KEYS:按照模式查找 key
KEYS 用于查找当前数据库中符合指定模式的 key:
bash
KEYS pattern #KEYS 命令只能接受一个匹配模式,不能同时写多个 pattern。

这里的 pattern 不是普通字符串,而是支持通配符的匹配模式。例如数据库中存在:
bash
hello
hallo
hbllo
hllo
heeeello
Redis 常见的模式匹配规则如下:
| 模式 | 含义 | 示例 |
|---|---|---|
* |
匹配任意数量字符,包括 0 个字符 | h*llo |
? |
匹配任意一个字符 | h?llo |
[ae] |
匹配集合中的任意一个字符 | h[ae]llo |
[^e] |
匹配除指定字符以外的一个字符 | h[^e]llo |
[a-b] |
匹配指定范围内的一个字符 | h[a-b]llo |
例如:
bash
127.0.0.1:6379> KEYS h?llo
1) "hello"
2) "hallo"
3) "hbllo"
其中 ? 只能匹配一个字符,因此 hllo 和 heeeello 都不符合要求。而:
bash
127.0.0.1:6379> KEYS h*llo
其中 * 可以匹配任意长度的字符,因此既可以匹配 hllo,也可以匹配 hello、heeeello。
方括号用于进一步限定单个字符。例如:
bash
KEYS h[ae]llo
只允许对应位置出现 a 或 e,因此可以匹配 hallo 和 hello。如果使用:
bash
KEYS h[^e]llo
则表示该位置不能是 e,因此 hello 不再匹配。
KEYS 使用非常直观,但它也是 Redis 中需要重点注意的命令。其时间复杂度为 O(N),其中 N 是当前数据库中的 key 数量。
执行 KEYS * 时,需要遍历整个数据库中的 key;当数据库只有几十个或者几百个 key 时通常感觉不到明显影响,但如果线上 Redis 中存在几十万甚至上百万个 key,全量遍历就可能占用较长时间。
Redis 的核心命令执行过程是串行推进的。一个耗时较长的命令没有执行完成时,其他客户端请求也会受到影响。因此在生产环境中直接执行KEYS *,可能把原本非常快的 Redis 变成一个明显的阻塞点。
生产环境并不是开发机器的另一种称呼。 软件通常会经历办公环境、开发环境、测试环境以及线上生产环境。办公环境主要承担日常工作;开发环境用于编码、编译和调试,可能是开发者本机,也可能是公司内部服务器;测试环境用于验证程序是否符合预期;生产环境则是真正部署业务、直接承载用户请求的环境。开发和测试环境中的一次慢操作通常影响有限,而生产环境中的阻塞操作可能直接影响真实用户,因此线上 Redis 对危险命令必须更加谨慎。
如果线上确实需要遍历大量 key,不应简单依赖一次性全量扫描,而应采用增量遍历一类的方案,例如 SCAN,避免一次操作长时间占用 Redis。
2.2 EXISTS:判断 key 是否存在
EXISTS 用于判断一个或多个 key 是否存在:
bash
EXISTS key [key ...]
对于单个 key,存在返回 1,不存在返回 0:
bash
127.0.0.1:6379> EXISTS hello
(integer) 1
EXISTS 也可以一次判断多个 key,返回值表示参数中存在的 key 的数量:
bash
127.0.0.1:6379> EXISTS hello hallo aaa
(integer) 2
KEYS 是搜索命令,需要遍历整个 Redis 数据库;EXISTS 是查询命令,通过 Redis 内部哈希表直接定位 key,不需要遍历整个数据库。
如果 hello 和 hallo 存在,而 aaa 不存在,结果就是 2。需要注意,Redis 统计的是参数中的存在次数,因此同一个已经存在的 key 被重复传入时,也会被重复统计:
bash
127.0.0.1:6379> EXISTS hello hello
(integer) 2
对于单个 key 的判断可以视为常数级查找;一次传入多个 key 时,则需要依次检查这些参数,因此整体开销会随着参数数量增长。
Redis 本身是客户端---服务器程序。无论通过 redis-cli 还是 Java、C++ 等语言的 Redis 客户端,底层最终都要将命令发送到 Redis 服务端,再等待服务器返回结果。客户端库中看到的各种 API,本质上就是对 Redis 命令以及网络通信过程进行了一层封装。
这也意味着,程序性能不能只考虑服务器内部执行一条命令需要多少 CPU 时间,还需要考虑网络 I/O 和请求次数。如果一条 Redis 命令本身支持一次操作多个 key,在场景允许的情况下使用批量参数,往往可以减少多次独立请求带来的网络往返开销。不过批量操作同样不能无限扩大,一次处理的数据过多仍然可能让单条命令执行时间变长。
2.3 DEL:删除指定 key
1.DEL 和 EXISTS 类似,不会遍历整个 Redis。它也是通过 key 直接定位删除。2.
FLUSHALL 是 Redis 实例级别的数据清理命令,它会清空所有逻辑数据库中的所有 key。默认同步执行,数据量大时会阻塞 Redis,因此生产环境通常谨慎使用,必要时使用 FLUSHALL ASYNC 降低主线程阻塞风险。
DEL 用于删除一个或多个 key:
bash
DEL key [key ...]
返回值表示本次实际删除的 key 数量。不存在的 key 不会报错,也不会计入删除数量:
bash
127.0.0.1:6379> DEL hello
(integer) 1
127.0.0.1:6379> DEL hello hallo aaa
(integer) 2
第二条命令即使传入三个 key,只要实际只有两个存在,最终返回值就是 2。
删除操作本身并不复杂,但在生产环境中需要非常谨慎。数据库中的删除一直属于高风险操作,例如关系型数据库中的 DROP DATABASE、DROP TABLE、DELETE,Redis 中的 DEL 同样意味着对应数据被直接移除,而不是简单地"隐藏"起来等待恢复。
Redis 经常被作为缓存使用。在这种架构中,真正完整的数据可能保存在 MySQL 等持久化数据库中,即使某些 Redis key 被误删,业务仍有机会重新从数据库加载数据,只是可能造成缓存失效、数据库压力上升等问题。但是如果 Redis 本身承担的是主要数据存储、消息队列或其他无法简单重建的数据职责,错误的DEL就可能直接造成业务数据丢失。
此外,不能简单地把所有 DEL 都理解成完全没有成本。删除一个普通 String key 通常很快,但如果 value 本身是包含大量元素的 List、Set、Hash 或 ZSet,释放其内部数据同样需要时间。因此删除 key 的风险不仅来自"删错数据",也来自删除超大对象可能带来的执行开销。
2.4 EXPIRE、PEXPIRE:设置 key 的生命周期
很多数据从业务角度就不应该永久存在。例如验证码只应该在几分钟内有效,某些优惠信息只在指定时间段内有效,缓存数据也通常需要在一段时间后重新加载。Redis 因此允许直接为 key 设置过期时间。

EXPIRE 使用秒作为时间单位:
bash
EXPIRE key seconds
例如让 code:1001 在 300 秒后过期:
bash
127.0.0.1:6379> SET code:1001 9527
OK
127.0.0.1:6379> EXPIRE code:1001 300
(integer) 1
设置成功返回 1;如果指定的 key 根本不存在,则返回 0。
如果需要更高的时间精度,可以使用 PEXPIRE,它以毫秒为单位:
bash
PEXPIRE key milliseconds
因此:
bash
PEXPIRE task 3000
表示让 task 在大约 3000 毫秒后失效。
过期机制除了缓存和验证码之外,也经常用于具有生命周期的数据。例如某些临时状态只允许存在几分钟,时间一到便自动失效;实现分布式锁时,也通常需要为锁设置合理的过期时间,避免持有锁的进程异常退出后锁永远无法释放。
这里需要理解一个关键概念:Redis 中设置过期时间,是把生命周期附加到 key 上,而不是附加到 value 的某一部分。 一旦 key 到期,这个 key 以及它对应的整个 value 都会失效。
补充:Redis 一个 key 只有一个过期时间,EXPIRE 和 PEXPIRE 本质都是修改这个过期时间,因此后设置的会覆盖先设置的,不会累加。
| 操作 | 是否覆盖 TTL | 详细说明 | 示例 |
|---|---|---|---|
EXPIRE key seconds |
✅ 覆盖 | 给 key 设置过期时间。如果原来有 TTL,则直接替换;没有 TTL,则新增 TTL | EXPIRE name 100 |
PEXPIRE key milliseconds |
✅ 覆盖 | 和 EXPIRE 一样,只是单位是毫秒。如果之前是秒级 TTL,也会被替换 | PEXPIRE name 5000 |
EXPIRE → PEXPIRE |
✅ 覆盖 | 后执行的命令覆盖前面的 TTL,不会叠加 | 先 EXPIRE name 100,再 PEXPIRE name 5000,最终 5 秒后过期 |
PEXPIRE → EXPIRE |
✅ 覆盖 | 同理,后面的 EXPIRE 覆盖前面的 PEXPIRE | 先 PEXPIRE name 5000,再 EXPIRE name 100,最终 100 秒后过期 |
SET key value |
✅ 删除 TTL | 重新设置 value 时,会清除原来的过期时间,key 变成永久存在 | SET name Jack 后 TTL 变为 -1 |
DEL key |
✅ 删除 TTL | 删除整个 key,value 和 TTL 都不存在 | DEL name |
PERSIST key |
✅ 删除 TTL | 保留 key 和 value,只删除过期时间 | TTL 变为永久 |
INCR key |
❌ 不影响 TTL | 修改 value,但不会删除过期时间 | 计数器常用 |
HSET key field value |
❌ 不影响 TTL | 修改 Hash 内部数据,不影响 key 的 TTL | 用户信息缓存常用 |
LPUSH key value |
❌ 不影响 TTL | 修改 List 内容,不影响 key 的 TTL | 消息队列常用 |
2.5 TTL、PTTL:查询剩余生命周期
设置过期时间后,可以使用 TTL 查询 key 还剩多少秒:
bash
TTL key
例如:
bash
127.0.0.1:6379> TTL code:1001
(integer) 287
表示该 key 大约还剩 287 秒。
如果需要毫秒级精度,则使用 PTTL:
bash
PTTL key
TTL 是 Time To Live 的缩写,即剩余生存时间。网络协议中也存在 TTL 这个名称,例如 IP 协议中的 TTL,但两者具体语义并不完全相同;在 Redis 中,它非常直接地表示 key 距离失效还剩多长时间。
至此,一个带生命周期的 Redis key 可以形成完整过程:
bash
SET session:1001 xxx
EXPIRE session:1001 300
TTL session:1001
GET session:1001
先创建数据,再设置生命周期,之后可以随时查询剩余时间;当生命周期结束后,再访问这个 key 时,就会表现为不存在。
3.Redis 过期 key 的实现思路
给 key 设置过期时间看起来只是执行了一条 EXPIRE 命令,但真正需要解决的问题是:Redis 如何知道某个 key 已经过期,又应该在什么时候把它删除?
一种最直接的想法是不断扫描所有带过期时间的 key,检查当前时间是否已经超过它们的截止时间。但如果 Redis 中存在大量 key,这种方式会持续消耗大量 CPU,因此 Redis 不会简单地不停遍历整个数据库。
Redis 的过期处理主要结合了定期删除 和惰性删除两种思路。
3.1 定期删除与惰性删除
定期删除 的核心思想 不是每次检查所有 key,而是在一定时间间隔内抽取一部分带过期时间的 key 进行检查,将其中已经过期的数据删除。这样能够主动回收过期数据,又不需要每一次都扫描完整数据库。
惰性删除 则将检查时机推迟到 key 被访问的时候。一个 key 即使已经超过过期时间,也不要求在时间到达的那一瞬间立刻执行删除;后续客户端再次访问这个 key 时,Redis 发现它已经过期,就将其删除,并按照 key 不存在进行处理。
两种方式结合后,可以在 CPU 与内存之间取得平衡:定期删除负责主动清理一部分过期数据,惰性删除负责保证客户端不会读取到已经过期的数据。
如果只采用定期删除,就必须决定多久扫描一次以及一次检查多少 key。扫描过于频繁会浪费 CPU,扫描过少又可能让大量已经过期的数据长期占用内存;如果只采用惰性删除,一些过期后再也没有被访问的 key 就可能长时间停留在内存中 。因此两种策略互相补充。
这也是为什么一个 key 的逻辑过期时间到达后,并不意味着 Redis 必须在那个时间点精确地启动一个独立线程把它删除。"已经过期"与"物理内存已经立即释放"是两个不同概念。
Redis 在内存不足时还涉及内存淘汰机制,但内存淘汰和 key 的过期删除解决的是两个不同问题:前者主要解决内存容量压力,后者解决数据生命周期。
Redis 的定期删除是在内部时间事件循环(serverCron)中周期执行的,通过随机抽样检查过期字典中的 key 并删除;惰性删除是在客户端访问 key 时检查 TTL,如果发现过期再删除。两者结合避免了全量扫描导致性能下降,同时减少过期 key 长时间占用内存的问题。
3.2 为什么不为每个 key 创建一个定时器
既然已经知道每个 key 的过期时间,看起来还可以为每一个 key 单独创建一个定时任务:时间一到,立即删除这个 key。少量任务时这种设计很直观,但如果存在几十万甚至几百万个带过期时间的 key,就意味着需要维护大量定时任务。
因此,定时任务系统通常不会真的简单地"一个任务创建一个独立线程",而是借助统一的数据结构管理大量任务。比较典型的实现思路包括基于优先级队列的定时器 和时间轮。
需要注意,这两种方案是通用的高效定时器设计思路,并不代表 Redis 对过期 key 就是直接按照这两种结构实现的。理解它们主要是为了理解"大量定时任务应该如何统一调度"。
3.3 基于优先级队列的定时器
普通队列强调先进先出,而优先级队列会根据元素的优先级决定谁先出队。对于定时任务而言,最自然的优先级就是任务的到期时间:过期时间越早,优先级越高。
假设有三个 key:
bash
key1 -> 12:00
key2 -> 13:00
key3 -> 14:00
如果按照过期时间组织成优先级队列,那么队首始终是最早需要处理的 key1。定时线程只需要关注队首元素,而不需要遍历所有任务。
如果当前是 11:00,而队首任务 12:00 才到期,那么线程完全没有必要持续高速检查,可以根据当前时间与 12:00 之间的时间差进入等待;到达时间后再唤醒并处理任务。删除 key1 后,新的队首变成 key2,再按照它的到期时间继续等待。
这种设计把"大量任务的逐个扫描"转换成了"始终关注最近到期的任务",可以明显减少无意义的检查。
但它还必须处理一个问题:假设线程原本正在等待 12:00 的任务,此时突然新增了一个 11:30 就要执行的任务,那么原来的等待时间已经不再正确。系统需要能够唤醒等待线程,重新计算下一个真正应该执行的任务。
3.4 时间轮
另一类常见定时器实现是时间轮。它可以想象成一个不断旋转的表盘,整个圆环被划分成若干个时间槽,每个槽负责某一段时间范围。
每个槽上可以挂一个链表,链表中的节点代表需要执行的任务。任务节点中保存需要执行的操作以及相应参数,在不同语言中可以表现为函数指针、回调对象或任务对象。
假设时间轮每隔 100ms 向前移动一个槽:
text
0ms → 100ms → 200ms → 300ms → ...
如果某个任务需要在 3000ms 后执行,就可以按照时间差计算它应该进入哪个槽。时间轮的指针每经过一个槽,就处理该槽链表中的到期任务。
这种方式不要求系统不断遍历所有定时任务,而是随着时间推进,只处理当前位置对应的任务集合。时间槽的数量、每个槽代表的时间以及是否需要多级时间轮,都需要根据实际场景设计。时间精度越高,槽通常越密集;能够表示的时间范围越大,所需要管理的结构也会更加复杂。
基于优先级队列的定时器和时间轮都是大量定时任务中常见的设计方案,但 Redis 的 key 过期机制并不是简单地为每个 key 创建一个这样的独立定时任务。
3.5 Redis 的事件循环
Redis 源码中一个非常核心的机制是事件循环。Redis 不断通过事件循环处理客户端请求、网络事件以及周期性任务 。在 key 过期问题上,Redis 更倾向于把过期检查作为服务器周期性工作的一部分,再结合访问 key 时的惰性检查完成数据清理,而不是为每一个带 TTL 的 key 单独维护一个定时器。
这种设计本质上仍然是在做取舍:如果追求"某个 key 到期的那一毫秒就必须立即从内存删除",会引入更多任务管理和 CPU 开销;Redis 更关注的是在保证逻辑过期正确性的同时,以合理成本完成内存回收。
因此,对于应用程序而言,只需要关心 key 到期以后不能继续作为有效数据读取,并不应该依赖"到期瞬间物理内存一定已经释放"这一假设。
4.TYPE:查询 value 的数据类型
Redis 中所有 key 都可以看作字符串,但 key 对应的 value 可以使用不同的数据类型。TYPE 命令用于查询某个 key 当前对应的 value 类型:
bash
TYPE key
常见返回结果包括:
string、list、set、zset、hash、stream。
如果 key 不存在,则返回:none
例如:
bash
127.0.0.1:6379> SET name redis
OK
127.0.0.1:6379> TYPE name
string

TYPE 的时间复杂度为 O(1),因为 Redis 已经知道一个 key 当前关联的对象类型,不需要遍历 value 内容才能完成判断。
这里需要区分两个概念。Redis 对外提供的数据结构除了 String、List、Set、Hash、Sorted Set、Stream 之外,还有 Geospatial、HyperLogLog、Bitmap、Bitfield 等面向特殊场景的能力;但这些结构中的一部分实际上建立在基础数据类型之上。例如 Bitmap、Bitfield 本质上围绕 String 进行位操作,Geospatial 建立在 Sorted Set 能力之上。因此 TYPE 更关注一个 key 在 Redis 内部属于哪种核心 value 类型,而不是它当前被业务拿来完成什么功能。
不同数据类型的命令差异很大。例如 String 有自己的读写操作,List 围绕列表两端进行操作,Hash 围绕字段和值组织数据,ZSet 则同时维护成员与分数。因此在进入具体数据结构之前,首先掌握这些不依赖 value 类型的通用命令,可以建立完整的 Redis key 管理基础。
5.Redis 通用命令总结
Redis 通用命令的核心不是操作某一种具体数据结构,而是围绕 key 本身进行管理。当前涉及的主要命令可以归纳如下:
| 命令 | 作用 | 关键特点 | 时间复杂度 |
|---|---|---|---|
KEYS pattern |
查找符合模式的 key | 遍历当前数据库所有 key,生产环境尤其需要警惕全量扫描 | O(N)(N 为数据库中 key 的数量) |
EXISTS key [key ...] |
判断 key 是否存在 | 根据 key 直接从哈希表查找;返回存在的 key 数量 | O(M)(M 为传入的 key 数量,单个 key 时 O(1)) |
DEL key [key ...] |
删除 key | 根据 key 定位删除;返回实际删除数量 | O(M)(M 为删除的 key 数量;删除单个普通 key 时 O(1),大对象释放可能耗时) |
EXPIRE key seconds |
设置秒级过期时间 | 修改 key 的过期时间;已有 TTL 会被覆盖 | O(1) |
PEXPIRE key milliseconds |
设置毫秒级过期时间 | EXPIRE 的毫秒版本;已有 TTL 会被覆盖 |
O(1) |
TTL key |
查询剩余秒数 | 返回 key 剩余生存时间(Time To Live) | O(1) |
PTTL key |
查询剩余毫秒数 | TTL 的毫秒版本 |
O(1) |
TYPE key |
查询 value 类型 | 根据 key 直接获取对象类型 | O(1) |
其中最需要建立的三个认识是:KEYS 虽然简单,但全量扫描存在明显的线上风险;DEL 是实际删除操作,数据职责不同,删除风险也不同;过期时间并不是为每个 key 建立一个独立定时器,而是通过过期检查机制在正确性、CPU 和内存之间进行权衡。
掌握这些通用命令后,Redis 的整体结构就已经比较清晰:key 使用统一方式管理,而 value 根据业务需要采用不同的数据结构。 接下来围绕 String、List、Hash、Set、ZSet 等具体类型展开时,重点就会从"如何管理 key"转向"不同 value 结构如何组织和操作数据"。