第 23 章 —— 通过真实端口观察一致性边界
本章目标: 本章完成后,开发者能够用两个独立 RESP 客户端、真实 TCP/UDP 端口和 repair 诊断复现实例间传播,并解释为什么收敛不能撤回分区期间已经返回的成功。
学习目标
- 区分 RESP 命令层、本地 projection、DSM mutation batch 和复制/修复层。
- 用真实 socket 观察在线 delta、晚加入节点和 TCP repair。
- 复现两个
SET NX成功与重复 List pop。 - 把 E4 黑盒证据与生产部署验收分开。
前置条件
- 已完成第 14 章分区窗口与第 18 章证据阶梯。
- 能使用 Java 25 和 Maven;手工演示可选安装
redis-cli。 - 接受这个示例实现 Redis-shaped 协议,不是 Redis 兼容产品。
案例进度
履约团队需要一个业务方也能看懂的黑盒实验。Node A 监听 RESP
6380,Node B 监听 6381;客户端只看到 Redis
风格命令和返回值,底层通过 UDP live delta 与 TCP repair 传播 mutation
batch。
一张图看懂实验边界
协议层接受 RESP2 bulk-string array,并限制 transaction queue 与 mutation batch 大小。projection 为 String、Hash、List、Set、TTL 和 counter 提供本地视图;DSM 复制的是确定性 mutation batch,不是把 Redis 服务器伪装成共享内存。
在线路径与修复路径
节点都在线时,后续写入通过 UDP live delta
传播。晚加入或漏掉在线消息时,节点通过 TCP data plane 交换
digest,并按可用窗口选择 replay 或 snapshot。INFO DSM
暴露本地 dsm_repair_state、最近模式、时间、peer
和错误。
这些字段是当前节点的诊断,不是全局一致查询。digest_match
只说明这次比较未发现差异。
分区时两个 OK 都是真的
SET key value NX 只检查入口节点当前 projection。隔离 A
与 B 后,两边都可能看见 key 不存在并返回 OK。恢复和 repair
会确定性收敛到一个状态,但另一个客户端已经收到的成功不能被撤回。
List 的 LPOP/RPOP 也依据本地
projection;分区期间两个节点可能弹出同一个元素。因此这个示例不能作为
exactly-once queue、全局 CAS 或库存扣减系统。
反例与故障注入
- 断开 live delta,在 A 与 B 对同一 key 执行
SET NX,记录两个返回值。 - 让两端对同一 List 元素执行 pop,确认两个客户端都可能获得该元素。
- 在 B 离线时向 A 写入 String 与 Hash,再启动 B,观察 bootstrap repair。
- 发送超过 32 KiB 的 mutation batch,确认整批拒绝而非部分应用。
实验
完整自动黑盒验证:
cd submodule/dsm-examples/dsm-redis-server
./mvnw -q clean verify手工边界演示:
cd submodule/dsm-examples/dsm-redis-server
./scripts/run-consistency-boundary-demo.sh使用 redis-boundary-observations.json
按「客户端返回、节点本地视图、repair
结果、不能推出的结论」记录观察。
实验验收卡
| 字段 | 内容 |
|---|---|
| 运行命令 | Redis-shaped example
clean verify;可选边界演示脚本 |
| 输入或故障 | 真实 RESP socket、UDP live delta、节点晚加入、分区、TCP repair |
| 可观察结果 | 命令可达;在线传播与 repair 可见;两个局部成功最终收敛 |
| 证据等级 | E4:独立 socket/真实端口/客户端协议黑盒;仍在本机 loopback |
| 本实验未证明 | Redis 完整兼容、跨主机网络、生产安全、持久化、全局 CAS 或 exactly-once |
回顾
- 真实端口提高执行面证据强度,但不会改变集合语义。
- online delta 与 repair 是两条互补路径。
- repair 让状态重新收敛,不会撤回已返回的业务成功。
- familiar protocol 只是观察入口,不能偷换成 Redis 产品承诺。
下一步
第 24 章把范围扩大到两个 cluster,并逐一说明 Register、Lease 和 CRDT 穿过 federation 边界时保留了什么、放弃了什么。