实测最终一致的对账与修复:10 万订单全量对账 0.36 s 发现全部 2068 个分歧(丢失、重复、金额不一致、孤儿)、0 误报;只比最近 1 小时只能发现 5%,支付库时钟慢 5 分钟会出 311 个误报;宽限期 1 秒消除途中订单的误报;幂等修复后重新对账 0 分歧,再修复 0 动作。
实测分布式锁与事务的关系:Redis 锁能把 800 次读改写从丢 699 次变成 0 丢失,但比原子 UPDATE 慢 10 倍;持有者被 SIGSTOP 冻住 1 秒、锁过期后 A 醒来照样写,计数器 2 变 1(写前检查也没用);fencing token 让旧持有者的写入被存储端拒绝;持锁者 kill -9 后转账少了 100,锁不是事务。
实测乐观锁:不保护的读改写 800 次丢 697 次;version CAS 丢 0 次,但同一行 8 线程每次成功平均试 7.02 次、32 线程 27.57 次,吞吐从 4573 降到 417 成功/秒;无冲突时一次成功;按状态值 CAS 有 208 / 300 次被 ABA 欺骗,version CAS 0 次;随机指数退避把 409 提高到 3332 成功/秒。
实测六种库存扣减方式抢 1000 件:先读后写 3000 个都成功超卖 2000;FOR UPDATE、条件 UPDATE、乐观锁、分片、Redis Lua 都是 0 超卖;乐观锁因争用只有 1121 请求/秒、库存充足时成功数也只有 2323 到 2349(应为 3000);Redis 没持久化被 kill -9 后按 MySQL 重建,超卖 526 件。
实测订单状态机:朴素 UPDATE 接受 30 条流转(25 条非法),带源状态条件只接受 5 条合法的;并发的支付与取消 1000 单读后写全部矛盾,条件 UPDATE 0 个;重复回调 1500 次只触发 500 次副作用;随机 2 万次尝试日志重放全部一致;触发器拦住绕过应用的非法 UPDATE。
手写一个最小的 AT 模式并实测:分支本地提交时写前后镜像到 undo_log 并申请全局锁;全局回滚按前镜像恢复;全局锁让 T2 等 825 ms,没有全局锁 T1 回滚会因脏写失败;普通写入绕过全局锁同样造成脏写;读到被回滚的 900 占 98%;一次分支更新 357 µs 变成 1991 µs。
手写 TM / RM / TC 三个独立进程的最小原型并实测:一次全局事务 12 次 HTTP 调用;TM 崩溃后 TC 超时(1.5 s)扫描器回滚;TC 在二阶段被 kill -9,重启后从 tc_db 恢复继续;RM 暂时失败 TC 退避重试,一直失败则全局锁一直被占、别的事务等 1034 ms 失败。
手写最小的 Percolator 风格事务并实测:原子性押在主锁那一次提交上;预写后 kill -9,读到的人等 1486 ms(TTL 1500 ms)后回滚;主锁提交后 kill -9,读到的人 0.7 ms 前滚;压力下会处理锁的快照读 215 次检查总额 0 次错,不管锁的读 3339 次错 11 次。
用真实的 3 节点 etcd 实测 Raft 的提交条件:多数(2/3)落盘才提交;杀 1 个 follower 写入延迟不变(7.74 → 7.83 ms)、重启后 164 ms 追上;只剩 1 个节点时写入超时,多数恢复后那次超时的写入反而被提交;手写模拟论文图 8:数副本数提交旧任期条目会被覆盖;延迟只取决于最快的多数(31.0 vs 31.5 ms)。
实测线性一致与最终一致:etcd 写后立刻读 follower,可串行化读旧值 101 / 300(加 20 ms 延迟后 300 / 300),线性一致读 0 次旧值但延迟从 0.91 ms 到 93.45 ms;Redis 异步复制写后读 replica 旧值 73 / 300,WAIT 1 0 后 0 次;手写线性一致性检查器判定:可串行化读 46 到 100 / 100 段历史不可线性化,线性一致读 0。
用 Redis 主从实测会话一致性:随机读 replica 时读己之写 184 / 1500 次读到旧值,偏移量令牌和写后读 master 都是 0;单调读随机选 replica 倒退 99 次,固定 replica 或记最大值是 0;因果上看到回复读不到帖子 57 / 300 次,检查依赖版本后 0 次。
3 个进程注入 [0, +50, -80] ms 的时钟偏差实测:物理时间戳让 140 / 276 条消息的接收早于发送;Lamport 保证因果但把 87.3% 的并发事件对排出了先后;向量时钟判定 100% 正确但消息头随节点数线性增长;HLC 因果 0 违反,l 与物理时间的差最大 130 ms;物理时钟做 LWW 丢 44.7% 的因果写入。