实测 Keyspace Notification:默认关闭;KEA 下一条命令产生 keyspace 与 keyevent 两条通知;expired 事件在空闲实例上比 TTL 晚 5.3 ms(中位),但池子里有 1000 个以上长 TTL key 时,30 个短 TTL key 的事件 20 秒内只到 22/30 以下(30 万个时 1/30);发后即忘;开启 KEA 使管道 SET 吞吐下降约 18%。
用 3 个本机 Redis 节点验证 PSYNC2:提升从库后它保留旧主的 replid 作为 replid2(second_repl_offset = 提升时 offset + 1);另一个从库改跟随新主、旧主降为从库重新加入,都是部分重同步(新主 sync_full 变化 0 / 0,partial_ok +1 / +1);毫无关系的新节点则只能全量同步。
100 万个 key 的主库,磁盘方式全量同步的实测时间线:BGSAVE 0.57 s → 传输 24.9 MB RDB 不到 0.03 s → 从库加载 0.59 s,共 1.18 s;同步期间主库写入 391 个 key 被缓冲后补发(最大输出缓冲 20504 字节),最终两边 dbsize 都是 1000391。
用手写的假从库直接对主库说 PSYNC 协议:PSYNC ? -1 得到 +FULLRESYNC 和一段 RDB(207 字节,REDIS0015);之后主库按 RESP 原样推送写命令(107 字节);断线后带 replid 和 offset+1 重连得到 +CONTINUE,补发的正是断线期间的 83 字节;replid 不对、offset 太大或太旧都会回 +FULLRESYNC。
在本机主从上验证从库只读限制:默认 replica-read-only yes 时 SET/DEL/EXPIRE/INCR/FLUSHALL 与 EVAL 里的写命令都报 READONLY,PUBLISH 和 EVAL_RO 允许;改成 no 后本地写入不会同步给主库、数据分叉;全量重同步会清掉从库本地写入,部分重同步则不会;可写从库上带 TTL 的 key 由从库自己过期。
在本机一主两从上验证 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。
本机实测无盘复制:默认 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 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% 处自动触发。
在 150 万个 key 的实例上观察 AOF Rewrite 期间的增量:发起重写的瞬间主进程新建 incr.2,旧 incr.1(201.9 MB)停止增长;重写期间 4 个线程完成 86125 次 INCR 全部写进 incr.2;INFO 里没有重写缓冲区字段;kill -9 后从 AOF 重启,seq = 86125 与确认数 86125 一致。
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 命令。
亲手弄坏 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 可以)。
实测 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(无)。