土法炼钢兴趣小组的算法知识备份

【FoundationDB 内核】生产排障:超时、冲突、切换、落后

文章导航

分类入口
databasestorage
标签入口
#foundationdb#troubleshooting#transaction-timeout#conflict#sequencer#storage-lag

目录

机制已经沿 Proxy → Sequencer → Resolver → TLog → Storage 走通。生产告警往往只给一句「延迟高 / 报错多」。本文把四类高频问题——事务超时、冲突风暴、Sequencer 切换、Storage 落后——收成症状 → 机制决策树,并回链本系列对应章节。具体阈值以 7.x 官方文档为准,正文不承诺适用于所有集群的固定参数。

版本锚定:FoundationDB 7.x Developer Guide / Known Limitations / Administration;恢复机制见 Zhou et al., SIGMOD 2021 §2.4.4。


一、总决策树:先分流再下钻

flowchart TD
  SYM["Symptom: latency errors retries"]
  SYM --> Q1{"transaction_too_old or 5s window?"}
  Q1 -->|yes| TIMEOUT["Txn timeout path<br/>Section 2"]
  Q1 -->|no| Q2{"High not_committed conflict rate?"}
  Q2 -->|yes| CONF["Conflict storm<br/>Section 3"]
  Q2 -->|no| Q3{"Recovery or Sequencer restart in status?"}
  Q3 -->|yes| SEQSW["Sequencer epoch switch<br/>Section 4"]
  Q3 -->|no| Q4{"Storage versions lag TLog / slow reads at latest?"}
  Q4 -->|yes| SSLAG["Storage lag<br/>Section 5"]
  Q4 -->|no| OTHER["Client network disk Ratekeeper<br/>see ops article"]
分流问题 优先信号 机制锚点
是否踩 5 秒 / 过大事务 transaction_too_old、官方限制文档 第 9 篇
是否 OCC 冲突 not_committed、重试风暴 第 8 篇
是否世代恢复 status 恢复中、角色重招 第 13 篇
是否存储追日志慢 读最新版本等待、SS 与 TLog 间隙 第 10–11 篇

二、事务超时与「事务过旧」

2.1 机制

Known Limitations:自事务第一次读起超过约 5 秒,后续需访问数据库的读通常报 transaction_too_old;带写的提交也会以 transaction_too_oldnot_committed 失败。这与严格可串行化下的 MVCC 窗口、冲突历史有界绑定(第 9 篇),不是客户端「随便设的 timeout」。

另两组常被混谈的限制:

2.2 症状 → 动作

flowchart TD
  E["Error: transaction_too_old"]
  E --> A{"Txn held open across user think time?"}
  A -->|yes| APP["Close txn; move interactive work out"]
  A -->|no| B{"Huge read or write set?"}
  B -->|yes| SPLIT["Split into small txns or indirection"]
  B -->|no| C{"Cluster recovering?"}
  C -->|yes| WAIT["Retry after epoch recovery Section 4"]
  C -->|no| D["Check client RTT and SS read stalls"]

处置方向(机制级):


三、冲突风暴

3.1 机制

Resolver 在 commit 版本已分配后做 OCC 冲突检测(第 8 篇)。读集与并发写集相交则 abort,客户端按 API 契约重试。冲突风暴的典型样貌是:CPU 与网络仍「忙」,但成功提交比例下降,重试放大写路径负载。

3.2 分流

观察 更可能原因 方向
冲突集中在少数 key 前缀 业务热点 / 计数器 原子操作、打散键、降低读改写
冲突随二级索引写入升高 Record Layer 索引扇出 检查索引设计(第 15 篇)
冲突在恢复后短时升高 重试叠加 退避;确认恢复已结束
几乎无冲突但提交仍慢 不是冲突风暴 转到 §四 / §五
flowchart LR
  CONF["Conflict storm"]
  CONF --> HOT["Hot keys"]
  CONF --> IDX["Index amplification"]
  CONF --> RETRY["Retry amplification"]
  HOT --> FIX1["Atomic ops or key shatter"]
  IDX --> FIX2["Narrow indexes"]
  RETRY --> FIX3["Backoff and find root latency"]

不要把 Ratekeeper 限速误判成「冲突」:限速是过载保护(第 16 篇),冲突是 Resolver 语义拒绝。


四、Sequencer 切换与写暂停

4.1 机制回顾

任一被 Sequencer 监视的 Proxy / Resolver / LogServer 失败,或配置变更,Sequencer 终止;ClusterController 招募新 Sequencer,开新 epoch(第 13 篇)。窗口内旧 TLog 停写,新世代未接受提交前,写路径不可用。论文生产观测恢复常在约 5 秒量级(作者数据,非本站实测)。

4.2 症状

4.3 排障顺序

  1. 确认是否在做配置变更、排除进程、升级——预期内切换。
  2. 若非预期:查哪一类角色先失败(TLog 磁盘、Proxy OOM、网络分区)。
  3. 切换频繁时,优先查 TLog 稳定性与磁盘,因为 LogServer 失败会逼出完整恢复路径。
  4. 客户端保持幂等重试;不要在半恢复窗口对同一业务键做「人工补偿双写」。
sequenceDiagram
  participant OPS as Operator
  participant ST as fdbcli status
  participant CL as Clients

  OPS->>ST: Observe recovery flags
  ST-->>OPS: New Sequencer recruited
  CL->>CL: Commits fail then succeed
  OPS->>OPS: If frequent find first failing role

五、Storage 落后于 TLog

5.1 机制

提交在 TLog 持久化并满足复制后即可向客户端确认;Storage 异步拉日志(第 10–11 篇)。因此存在「已提交但某 SS 尚未追上」的间隙。FDB paper Figure 3 展示过某一生产集群上的 lag 分布——说明间隙存在且通常很小,但不是零,也不能把该图数字当成你的 SLO。

读最新版本时,若 SS 尚未具备该版本,请求会等待或走文档所述的延迟路径;慢性落后则表现为读尾延迟升高、落后副本上的局部现象。

5.2 决策

flowchart TD
  LAG["Suspect storage lag"]
  LAG --> R{"Only some SS slow?"}
  R -->|yes| DISK["Disk IO network on those processes"]
  R -->|no| W{"Write rate vs apply capacity?"}
  W -->|yes| SCALE["Add storage or reduce write burst"]
  W -->|no| REC{"Just finished recovery?"}
  REC -->|yes| RV["Expect catch-up after RV; watch progress"]
  REC -->|no| ENG["Check storage engine health Redwood or SSD"]

与恢复的交叠:epoch 切换后 Storage 可能丢弃高于 RV 的内存版本再从新 TLog 拉——短时「落后」是预期,应观察是否收敛,而不是立刻当硬件故障。

5.3 读等待与「假冲突」

客户端若在 SS 尚未追上时频繁重试整笔事务,可能把等待可见版本放大成冲突与超时混合物。排障时应先看:

  1. 错误码是否主要是冲突类,还是读超时 / 版本不可用类;
  2. 落后是否只在部分 SS(局部磁盘/网络)还是全局写爆;
  3. Ratekeeper 是否已在限速(第 16 篇)——限速时加压重试会更糟。

六、把排障接回测试与运维

手段 作用
第 14 篇 模拟 正确性与恢复竞态;不解释你集群的磁盘尾延迟
第 16 篇 画像 扩哪类角色、备份/DR 边界
本篇决策树 线上症状分流

三者一起用:模拟保证「这类故障恢复逻辑存在」,运维保证「角色资源大致匹配」,排障保证「当前告警落到具体机制」。

6.1 最小取证清单

在改配置或扩容前,尽量留下:

取证不足时,优先观察一个恢复/冲突窗口再动作,避免同时改键、加机器、关 Ratekeeper 导致无法归因。

6.2 四类问题的「先看什么」速查

先看 不要先做
超时 事务持有时长、读写集大小、是否恢复中 盲目加大客户端 timeout
冲突 热 key、索引扇出、重试率 关掉冲突检测(不存在这种开关)
Sequencer 切换 是否变更/角色失败、切换频率 在窗口内人工双写补偿
Storage 落后 局部 vs 全局、磁盘、是否刚恢复 立刻当「数据丢失」做还原

七、学术谱系、工程间隙与开放问题

谱系:OCC + 有界 MVCC 窗口(FDB 事务模型)→ 失败收敛到恢复(SIGMOD 2021)→ 日志与存储解耦带来的可见性间隙(同论文 §2.4)。

工程间隙:公开文档对「该看哪个指标面板」的描述随部署(裸机、Kubernetes Operator、托管)而变;本篇只钉机制分流,不绑定某一套 Grafana JSON。

开放问题

  1. 冲突率与 Ratekeeper 限速同时升高时,缺少统一的「根因归因」标准信号。
  2. Storage lag 的用户可见 SLO 如何定义(P99 读最新 vs 允许读略旧)仍属产品策略。
  3. 频繁 epoch 切换的「健康阈值」无官方单一数字。

八、常见误解

误解一:所有超时都是网络问题。
先区分 transaction_too_old(窗口)、冲突重试耗尽、恢复写暂停三类。

误解二:Storage 落后说明提交丢失。
提交确认点在 TLog;落后影响的是读可见时机,不是默认丢提交(除非与 RV 回滚等恢复语义叠加,见第 13 篇)。

误解三:提高客户端 timeout 就能做长事务。
服务端 5 秒限制不会因客户端 timeout 变长而消失。


九、小结

三句话小结:

  1. 先用总决策树把症状分到超时、冲突、Sequencer 切换、Storage 落后四条机制链,再下钻。
  2. 超时绑定 5 秒窗口与事务大小限制;冲突风暴要拆热点、索引与重试放大;切换对应 epoch 写暂停;落后对应异步 apply。
  3. 排障不替代模拟与容量规划;无本站实测输出时,以官方错误码与 status 实跑结果为准。

参考资料

  1. FoundationDB 7.x Known Limitations(5 秒、事务大小、读均衡限制)。
  2. Zhou J., et al. FoundationDB…. SIGMOD 2021. §2.4 事务与恢复;Figure 3 storage lag。
  3. 第 8–11、13、16 篇

上一篇运维与容量:角色资源画像
下一篇选型与阅读地图

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .