985 字
约 3 分钟
12
S27-J01 · 分布式可靠性四件套:业务 Key、Single-flight、僵尸 Owner、Stage

适用读者:要解决"重复请求、缓存击穿、任务卡死"的人。
前置:S17-J03(幂等)、S12-J01(击穿)。
实测环境:Python 并发模拟(2026-11-06)。
覆盖旧文:131(796) 128(411) 125(391) 129(413) 130(455) + 相关 = 2,596 点。
覆盖扩展:E-S27-006(业务 Key)、E-S27-007(Single-flight)。
上一篇:S27-B04 · 微信生态:扫码登录与支付
下一篇:S27-J02 · 缓存预热与分布式锁。


1. 一句话结论

四个问题其实是同一件事的四种表现:谁在"重复做同一件事",以及"谁占着资源不干活"。

问题 本质 解法
业务 Key 同一业务被重复提交 唯一键 + 幂等
Single-flight 同一数据被并发请求 合并为一次上游调用
僵尸 Owner 锁/任务持有者已死 租约 + 心跳 + 过期
Stage 标签 请求生命周期不可见 统一阶段标记

2. 业务 Key:唯一性的落点(E-S27-006)

落点 优点 缺点
客户端生成 key 提前防重 可伪造
服务端按业务要素生成 可信 要素要选对
数据库唯一索引 最终兜底 冲突要处理

判据:"这个 key 能唯一标识"一次业务意图"吗?" 不能(如时间戳)→ 会误判。


3. Single-flight:实测 41 次 → 1 次(E-S27-007)

模拟:100 个并发请求同一 key,上游耗时 20ms。

方案 上游调用 耗时
无合并 41 次 54 ms
Single-flight 1 次 72 ms

读法:上游调用降 41 倍,代价是少量延迟(等第一次完成)。

实现要点 说明
同 key 只放一个请求进去 其余等待结果
失败要唤醒等待者 否则全部挂住
超时要设上限 防雪崩(S12-J01)

4. 僵尸 Owner 与租约

问题 后果
持有者崩溃未释放 资源永久锁死
网络分区 两个"Owner"并存

解法三件套:

① 租约(lease):锁有 TTL
② 心跳续约:活着就续,死了就过期
③ 单调递增的 fencing token:旧 Owner 的写被拒(防脑裂)

"为什么心跳不够":GC 停顿/网络抖动会导致"以为还活着"——fencing token 才是最终防线(S12-J03 的锁误删同源)。


5. Stage 标签:让请求可观测

阶段 用途
received 入口
validated 参数通过
upstream_called 调了外部
persisted 落库
done/failed 结束

"为什么要统一标签":排障时能一眼看出"卡在哪个阶段"——比翻日志快得多(S17-A02)。


6. 五个误区

误区 真相
"唯一索引就够了" 冲突异常要转成业务语义
"合并请求会降低吞吐" 实测上游降 41 倍
"锁有过期时间就安全" 需 fencing token
"心跳能证明活着" GC/网络会骗人
"阶段日志可有可无" 排障效率差一倍

7. 自检

  1. 四个问题的共同本质?
  2. 业务 Key 该在哪生成?
  3. 实测里 Single-flight 把上游调用从多少降到多少?
  4. 防僵尸 Owner 的三件套?
  5. 统一 Stage 标签的价值?

8. 下一篇

S27-J02 · 缓存预热与分布式锁

可靠性讲完,下一篇讲"预热为什么总和锁一起出现"。


本篇属于系列《S27 · 杂项归档与工具实测》。旧文来源:A-131/128/125/129/130 + 相关卡;扩展点 E-S27-006/007。Single-flight 数据为 Python 并发模拟。

S27-J01 · 分布式可靠性四件套:业务 Key、Single-flight、僵尸 Owner、Stage
https://www.clxhxhhr.top/posts/5619/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。