14.2 Redis 命令模型、事务与持久化
元数据卡
- 前置:14.1 内存优先数据库
- 关键词:Redis、原子命令、MULTI/EXEC、WATCH、RDB、AOF、复制
- 代码语言:Redis CLI
Redis 的优势来自“围绕数据结构设计命令”,不是把关系表搬进内存。String、Hash、List、Set、Sorted Set、Stream 等类型各自提供原子操作;选错结构会同时伤害内存、延迟和可维护性。
优先用原子命令,不要读—改—写
INCR item:42:view_count
HINCRBY item:42 stock -1
ZINCRBY ranking 15 player:7这些操作在命令边界上原子执行。若客户端先 GET、在本地计算、再 SET,多个客户端就可能覆盖彼此结果。
Redis 的命令执行从客户端视角大体是串行的,但现代 Redis 还使用后台线程、I/O 线程、子进程等完成其他工作。准确说法是“多数命令的核心数据结构操作在主执行线程上完成”,而不是“整个 Redis 只有一个线程”。慢命令、过大的 key 或 Lua 脚本仍可能拖住其他请求。
MULTI/EXEC 不是关系数据库事务
MULTI
DECRBY item:42:stock 1
INCR order:created
EXECMULTI 之后命令先排队,EXEC 时连续执行,不会与其他客户端命令交错。但它没有关系数据库式的自动回滚:某条命令在执行期因类型等原因失败,队列中其他命令仍可执行。
需要条件更新时,用 WATCH 做乐观检查:
WATCH item:42:stock
GET item:42:stock
MULTI
DECRBY item:42:stock 1
EXEC若受监视 key 在 WATCH 后被改动,EXEC 返回空结果,客户端必须重新读取、重新判断并有界重试。对多步校验更适合用服务端 Lua/Functions 把逻辑压缩成一次原子执行,但脚本也应短小并限制输入规模。
RDB:时间点快照
RDB 周期性生成数据集的紧凑快照。通常由子进程写临时文件,再原子替换旧快照,父进程继续服务;写时复制让父子初始共享内存页。
它的主要取舍:
- 文件紧凑,备份和大数据集重启通常较快;
- 两次快照之间的写入可能在故障中丢失;
fork()本身可能造成延迟,写密集期间 COW 会增加内存占用;- RDB 文件仍需复制到独立故障域,单机文件不是灾备。
不能机械地说峰值内存“一定翻倍”,实际取决于快照期间被改写的内存页比例、分配器和内核行为;容量规划应以压测峰值为准。
AOF:记录写命令并按策略刷盘
AOF 记录修改数据集的命令,重启时重放。appendfsync 的常见策略:
| 策略 | 确认路径 | 典型数据窗口 |
|---|---|---|
always | 每批写入都请求 fsync 后确认 | 最小,但仍受硬件和故障模型约束 |
everysec | 后台大致每秒 fsync | 故障时可能丢失最近约一秒写入 |
no | 交给操作系统刷新 | 窗口由操作系统策略决定 |
AOF 会增长,需要重写为能重建当前状态的更短表示。Redis 7 起采用 multi-part AOF:base 文件、一个或多个 incremental 文件及 manifest 共同描述有效日志集合。旧稿只写“一个 AOF 文件被换掉”已经不够准确。
同时启用 AOF 与 RDB
两者可以同时启用;重启时 Redis 会优先用信息更完整的 AOF 恢复。AOF base 可以使用 RDB 格式,这与“同时保存独立 RDB 快照用于备份”不是同一个概念。
持久化配置应从业务容忍度倒推:
- 纯可重建缓存可关闭持久化,但要验证缓存全失时数据库能否承受回源;
- 可接受秒级窗口时可评估 AOF
everysec; - 高价值权威数据还需要复制、备份、恢复演练和幂等写入,不能只靠 AOF;
WAIT能等待副本确认,却不会自动把 Redis 变成强一致 CP 数据库,故障切换仍可能受持久化与复制配置影响。
淘汰与持久化是两条轴
maxmemory-policy 决定内存达到上限时淘汰哪些 key;RDB/AOF 决定如何恢复已存在的数据。一个作为权威存储的实例若允许淘汰业务数据,即使 AOF 每次刷盘,也可能把淘汰操作忠实持久化。
因此必须明确实例角色:
- 缓存:允许淘汰,源数据可重建;
- 会话或队列:需要定义丢失、重复和过期语义;
- 权威状态:通常不允许任意淘汰,并需要比单节点持久化更完整的可靠性设计。
运维检查
INFO persistence
INFO memory
SLOWLOG GET 20
LATENCY DOCTOR关注最近 RDB/AOF 状态、重写是否卡住、fork/COW 内存、内存碎片、慢命令和主从延迟。恢复演练时要实际从备份启动新实例并校验 key 数、关键业务对象和应用读写,而不是只检查文件存在。
参考
完成这一章后,应能把“内存快”拆成数据布局、执行模型、持久化确认和恢复预算四个可验证问题。