知其然,知其所以然
Redis 2026-09-29

部分重同步

用手写的假从库直接对主库说 PSYNC 协议:PSYNC ? -1 得到 +FULLRESYNC 和一段 RDB(207 字节,REDIS0015);之后主库按 RESP 原样推送写命令(107 字节);断线后带 replid 和 offset+1 重连得到 +CONTINUE,补发的正是断线期间的 83 字节;replid 不对、offset 太大或太旧都会回 +FULLRESYNC。

Redis 复制 PSYNC 真实验证 动画演示
Redis 2026-09-29

从库只读限制

在本机主从上验证从库只读限制:默认 replica-read-only yes 时 SET/DEL/EXPIRE/INCR/FLUSHALL 与 EVAL 里的写命令都报 READONLY,PUBLISH 和 EVAL_RO 允许;改成 no 后本地写入不会同步给主库、数据分叉;全量重同步会清掉从库本地写入,部分重同步则不会;可写从库上带 TTL 的 key 由从库自己过期。

Redis 复制 只读从库 真实验证 动画演示
Redis 2026-09-29

WAIT

在本机一主两从上验证 WAIT:正常时 WAIT 2 中位 0.14 ms;冻结一个从库后 WAIT 2 200 等满超时(207 ms)只返回 1,WAIT 1 200 仍是 0.21 ms 就返回;WAIT 返回后写入并不回滚;WAIT 只等复制不等落盘,everysec 下 WAITAOF 1 1 耗时约 1018 ms。

Redis 复制 WAIT 真实验证 动画演示
Redis 2026-09-29

无盘复制

本机实测无盘复制:默认 repl-diskless-sync yes + repl-diskless-sync-delay 5,30 万 key 同步耗时 5.81 s(delay 0 时 0.29 s、磁盘方式 0.36 s);无盘时主库磁盘没有 dump.rdb;延迟窗口内的两个从库共用一次 BGSAVE(1 次);从库 repl-diskless-load swapdb 不落盘。

Redis 复制 无盘复制 真实验证 动画演示
Redis 2026-09-29

AOF Rewrite 过程

观察 Redis 8 的 AOF Rewrite:appendonlydir 里是 base(RDB 格式)+ incr(命令)+ manifest 三种文件;BGREWRITEAOF 会先新开一个 incr 再由子进程写新 base,10.7 MB 的 incr(30 万次 INCR + 5 万个 SET)折叠成 1.44 MB 的 base;auto-aof-rewrite-percentage 100 时在增长 192% 处自动触发。

Redis AOF 持久化 真实验证 动画演示
Redis 2026-09-29

AOF Rewrite 期间的增量缓冲

在 150 万个 key 的实例上观察 AOF Rewrite 期间的增量:发起重写的瞬间主进程新建 incr.2,旧 incr.1(201.9 MB)停止增长;重写期间 4 个线程完成 86125 次 INCR 全部写进 incr.2;INFO 里没有重写缓冲区字段;kill -9 后从 AOF 重启,seq = 86125 与确认数 86125 一致。

Redis AOF 持久化 真实验证 动画演示
Redis 2026-09-29

RDB 与 AOF 混合持久化

50 万个 key 实测三种持久化格式:AOF 开 RDB preamble(默认)base 39.4 MB、加载 0.215 s;关掉 preamble 的纯命令 base 50.9 MB、加载 0.374 s;纯 RDB 39.4 MB、0.222 s。混合持久化重启时先读 RDB base 再回放 incr 命令。

Redis RDB AOF 混合持久化 真实验证 动画演示
Redis 2026-09-29

AOF 文件损坏修复

亲手弄坏 AOF 文件再恢复:尾部半条命令时默认 aof-load-truncated yes 直接启动(丢 1 个 key),改成 no 就拒绝启动;文件中间损坏必然拒绝启动;redis-check-aof --fix 把文件截到 16303 字节,数据从 1000 个 key 剩 500 个;Redis 8 的 aof-load-corrupt-tail-max-size 需要大于损坏尾部的实际大小(16500 不够、20000 可以)。

Redis AOF 故障恢复 真实验证 动画演示
Redis 2026-09-29

RDB 文件校验

实测 RDB 文件校验:redis-check-rdb 在健康文件上报 Checksum OK;改掉一个 value 字节后 Redis 读完文件对不上 CRC64,拒绝启动;若 rdbchecksum no(末尾 8 字节全 0),同样的改动无人察觉,GET 返回被改坏的值;截断文件报 Unexpected EOF;100 万个 key 的 SAVE 中位 0.301 s(有校验和)vs 0.281 s(无)。

Redis RDB 校验和 真实验证 动画演示
Redis 2026-09-29

appendfsync always/everysec/no

本机实测 appendfsync 三种模式:单客户端同步 SET 的 p50 是 always 2.71 ms、everysec 31 µs、no 30 µs;管道吞吐 72k / 545k / 551k 条/秒;8 个客户端并发时 always 总吞吐放大 5.3 倍(多个写共用 fsync)。

Redis AOF fsync 真实验证 动画演示
Redis 2026-09-29

no-appendfsync-on-rewrite

在 200 万个 key 的实例上对比 no-appendfsync-on-rewrite:appendfsync always 且不跳过时,重写期间 SET p50 仍是 2.2 ms,重写要 6.6–8.6 s;设成 yes 后 p50 降到 30 µs、重写 1.1 s;everysec 下开关没有明显差别。

Redis AOF fsync 重写 真实验证 动画演示
Redis 2026-09-29

持久化对延迟的影响

量 BGSAVE 的 fork 停顿:内存 17 MB / 159 MB / 498 MB 时 latest_fork_usec 分别是 1.3 / 6.5 / 21.1 ms(约 41 µs/MB),持续写入时 BGSAVE 期间 SET 的最大延迟几乎等于 fork 耗时,而 p50 与 p99 不受影响(约 30 µs / 50–70 µs)。

Redis RDB fork 延迟 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号