← 返回模块
3.6.6.4beta 可读 · 未来付费校验通过内容版本 2026-05-29

系统设计、运维手册与事故响应实战

3.6.6 · 可观测性与系统设计 · 编程

国内私募量化的早盘 09:18,CFFEX IF 主力合约 tick 经过 feed-handler 落入 TimescaleDB,过去三周一切正常。今早值班手机突然弹一条飞书电话呼叫:『KafkaConsumerLagHigh:feedhandler-warehouse lag > 10000,持续 5m,runbook 见 https://runbooks.example.com/feed-handler/lag』。十二分钟后开盘,沪深300 期权做市策略需要新鲜 tick。你打开 runbook,按 detect / triage / mitigate / verify / post-mortem 五段走,按命令逐行执行——这就是本课要教的,把 L1 日志 + L2 指标 + L3 链路追踪三支柱仪表化的 feed-handler 配上完整的事故响应工作流,使一名 quant developer 在凌晨被叫醒时能在不到五分钟内止血、在两小时内复盘。

系统设计的头部词汇

值班之外,本课先确立四个 system-design 头部词汇(按本课的命名一次 + 深度指引方法呈现,不展开实现):

  1. 按标的分片(sharding by symbol):Kafka 按 symbol-hash 分区 + TimescaleDB hypertable 的 space-partitioning。深度指引到 3.6.4(Kafka 分区策略)+ 3.6.3(TimescaleDB 时空分区)。
  2. 灰度发布 / 金丝雀发布(canary deploy):交易服务的默认上线模式,小流量百分比限制爆炸半径。Argo Rollouts + Flagger 是 K8s 上的生产控制器;国内私募常自研发布工具。
  3. 蓝绿发布(blue-green deploy):瞬时切流量,状态迁移不允许部分流量时的正确选择。
  4. PTP 时钟同步(Precision Time Protocol):ptp4l + phc2sys + SO_TIMESTAMPING,深度指引到网卡厂商手册 + linuxptp README + IEEE 1588-2019。在接交易所直连 colocation(上海联通联和、上海移动中关村、深圳移动福田等)是标配,由网络团队而非 quant developer 维护。

这四个词汇是 quant developer 在系统设计评审中必须能命名、能解释一句话、能指向深度资料的——再深的实现归网络 / 平台 / SRE 团队。

完整的 runbook 模板

Fenced markdown 代码块,给出 L2 告警 KafkaConsumerLagHigh 的完整 runbook:

# Runbook: KafkaConsumerLagHigh

## Detect

- 告警表达式: max by (group, topic) (kafka_consumer_lag_messages) > 10000 for 5m
- Dashboard URL: https://grafana.example.com/d/feed-handler/feed-handler?viewPanel=12&refresh=15s
- Page 渠道: 飞书智能助手电话呼叫 / 钉钉机器人 + 阿里云 SMS

## Triage

- kubectl exec -n feed-prod kafka-0 -- kafka-consumer-groups --bootstrap-server localhost:9092 --describe --group feedhandler-warehouse
- kubectl get pods -n feed-prod -l app=feed-handler-consumer
- kubectl logs --previous deployment/feed-handler-consumer -n feed-prod | tail -200

## Mitigate

1. 扩容到 6 副本: kubectl scale deployment/feed-handler-consumer --replicas=6 -n feed-prod
2. 回滚最近发布: kubectl rollout undo deployment/feed-handler-consumer -n feed-prod
3. 若 broker 是瓶颈, 升级到平台团队
4. SLO 违约超过 15 分钟时启动 kill-switch: kubectl scale deployment/feed-handler-producer --replicas=0 -n feed-prod

## Verify

- 5 分钟内 lag < 1000
- Alertmanager 内告警状态变为 resolved

## Post-mortem

- 5 个工作日内, 走无责复盘模板

五个 section 标题(## Detect## Triage## Mitigate## Verify## Post-mortem)、四条 mitigation 命令顺序、dashboard URL 形状、5 个工作日的复盘窗口——全部按行业约定。runbook 是『可执行命令清单』,不是散文。

合成事故注入脚本

Fenced bash 代码块,scripts/inject-lag.sh,用于演练:

#!/usr/bin/env bash
set -euo pipefail
started=$(date -Iseconds); echo "Synthetic incident started at $started"
kubectl scale deployment/feed-handler-consumer --replicas=0 -n feed-prod
sleep 360
kubectl scale deployment/feed-handler-consumer --replicas=3 -n feed-prod
ended=$(date -Iseconds); echo "Synthetic incident ended at $ended"
echo "Dashboard: https://grafana.example.com/d/feed-handler/feed-handler"

set -euo pipefail 保证脚本错就停;scale 到 0 + sleep 360(6 分钟,比 for: 5m 略多)+ scale 回 3 是触发告警 + 触发 mitigation 后恢复的最小动作序列。namespace feed-prod 在国内私募实战中是生产环境的常用命名。

事故走查命令序列

Fenced bash 代码块,告警呼叫后值班执行的五步:

kubectl get pods -n feed-prod -l app=feed-handler-consumer
kubectl logs --since=15m deployment/feed-handler-consumer -n feed-prod | jq -c 'select(.level=="error")'
kubectl exec -n feed-prod kafka-0 -- kafka-consumer-groups --bootstrap-server localhost:9092 --describe --group feedhandler-warehouse
# Open Grafana Tempo search for trace_id of one delayed message
kubectl scale deployment/feed-handler-consumer --replicas=6 -n feed-prod

五条命令顺序:pod 状态、错误日志(L1 substrate)、Kafka 端 lag 复核、L3 trace 检索(手动步骤)、最后 mitigation。值班看到的不是一片散乱的命令,而是同一个工作流的有序节拍。

五阶段事故响应工作流

Inline-code 列举(顺序固定):

  1. Detect——告警触发,paging 渠道发送通知。
  2. Triage——10 分钟 SLA 内 ack(severity=page 级别);开事故频道;定 SEV-1 / SEV-2 / SEV-3 等级;找到 runbook URL。
  3. Mitigate——按 runbook 顺序执行;止血优先于定位根因。
  4. Verify——SLI 回到 SLO 内;告警 resolve;客户影响指标回基线。
  5. Post-mortem——无责,5 个工作日内完成;contributing factors 是复数;action items 必有 owner + due date。

严重性等级:SEV-1(客户已受影响)、SEV-2(已降级但有 workaround)、SEV-3(不影响客户)。规则:『止血先于根因;五个工作日内完成复盘;无责;factors 复数;action item 无 owner 无 due date 等于愿望,愿望不是结果』。

三种 SRE 衡量框架

Inline-code 列举(顺序固定,配合本课的 dashboard / runbook 使用):

  1. Google Golden Signals(Latency / Traffic / Errors / Saturation)——请求处理服务视角,对应 L2 dashboard 的五行。
  2. Brendan Gregg USE method(Utilisation / Saturation / Errors)——资源视角(CPU / 内存 / 磁盘 / 网络)。
  3. Tom Wilkie RED method(Rate / Errors / Duration)——请求流视角。

规则:『请求视角用 Golden Signals + RED;资源视角用 USE;按这三框架组织的 dashboard 任何 SRE 都能看懂』。

系统设计头部词汇汇总

Inline-code 列举(顺序固定,每个一句话 + 深度指引):

  1. 按标的分片——Kafka 分区按 symbol-hash + TimescaleDB hypertable 空间分区;深度指引到 3.6.4 + 3.6.3。
  2. 灰度发布——交易服务默认模式,小流量百分比限制爆炸半径;Argo Rollouts + Flagger 是 K8s 生产控制器。
  3. 蓝绿发布——瞬时切流量,状态迁移禁止部分流量时的正确选择。
  4. PTP 时钟同步——ptp4l + phc2sys + SO_TIMESTAMPING;深度指引到网卡厂商手册 + linuxptp README + IEEE 1588-2019。

复盘模板的五个 section

Inline-code 列举(顺序固定):

  1. Summary(一段话:发生了什么、何时、客户影响)。
  2. Timeline(UTC 时间戳:观察到什么、做了什么)。
  3. Contributing Factors(复数;抵制单一根因冲动)。
  4. Action Items(表格:action / owner / due date / 跟踪 issue)。
  5. Unknowns(调查结束时仍未知的部分)。

规则:『action item 无 owner 无 due date 就是愿望;愿望不是结果』。

练习

Exercise

Capstone——把 L1 + L2 + L3 三支柱仪表化的 feed-handler 走一遍完整事故。(a) 前提:feed-handler Deployment 在 feed-prod namespace 运行 3 个 consumer 副本;L1 结构化日志、L2 Prometheus 指标 + Grafana dashboard + 两条告警(KafkaConsumerLagHighDeploymentRolloutStuck)、L3 OTel trace + Tempo + Loki 全部接通。(b) 撰写 runbook runbooks/feed-handler/kafka-consumer-lag-high.md,按本课的 detect/triage/mitigate/verify/post-mortem 完整模板,包含四步 mitigation 与 dashboard URL。(c) 撰写 runbook runbooks/feed-handler/deployment-rollout-stuck.md,对第二条 L2 告警用同一模板。(d) 撰写复盘模板 runbooks/feed-handler/postmortem-template.md,含五个 section(Summary / Timeline / Contributing Factors / Action Items / Unknowns)。(e) 更新 L2 告警文件,使每条 alert 的 runbook_url annotation 指向对应 runbook(如 https://runbooks.example.com/feed-handler/kafka-consumer-lag-high)。(f) 撰写合成事故注入脚本 scripts/inject-lag.sh,含本课的 scale-to-0 + sleep-360 + scale-to-3 序列;chmod +x。(g) 打开 dashboard,自我声明为 on-call,执行 bash scripts/inject-lag.sh。(h) 告警触发后(约 5 分钟)执行本课的五条事故走查命令序列;记录每条命令输出。(i) 应用 mitigation kubectl scale deployment/feed-handler-consumer --replicas=6 -n feed-prod;记录 lag 回落到 1000 以下的时间,记录告警 resolve 的时间。(j) verify 之后 scale 回 3 副本。(k) 按模板写复盘,至少列 3 个 contributing factors(不是 1 个根因);至少 3 条 action items 各有真实 owner(你自己)+ 2 周内 due date。(l) 提交所有产物(runbooks/scripts/inject-lag.sh、更新后的 alerts/feed-handler.yml、复盘)并确认 runbook URL 可解析。

提示
事故注入脚本 sleep 一定要比 for: 5m 略长——本课用 360 秒(6 分钟)。短于 for: 时长告警永远不触发,演练就失败。
提示
复盘要列复数 contributing factors。仅写 1 条就是『单一根因冲动』;至少分『触发因子』『放大因子』『检测延迟因子』三类各 1 条,确保结论指向系统性改进而非个人责任。

跨区域阅读清单

Google SRE Book 中文译本《SRE: Google 运维解密》(电子工业出版社)是 golden signals、SLI / SLO / 错误预算、on-call、复盘的中文权威;《SRE 工作手册》(中信出版社, 2019)是实践配套;极客时间《SRE 实战 24 讲》(赵成)覆盖国内私募与互联网公司视角;极客时间《故障复盘实战》专门讲复盘;阿里巴巴《阿里云 SRE 实践手册》(电子版)含灰度发布、故障演练、复盘模板的中文阐述;字节跳动 SRE 公众号 / 知乎专栏的 on-call + 复盘文化系列文章;PingCAP 工程博客关于 SRE + 混沌工程的中文文章;Apache SkyWalking 中文文档(skywalking.apache.org/zh/);IEEE 1588-2019 标准(英文)是国内网络工程师 PTP 标准参考;linuxptp 项目 README(github.com/richardcochran/linuxptp)。一条额外注释:国内量化 firm 的 on-call 制度与美国相似(主备 + SLA 响应时间),但节假日排班、春节安排与国内节假日强绑定;等保三级环境对复盘留档的要求与海外金融监管不同,一般由信息安全 + 合规团队主导模板。

on-call 的实战节奏

国内私募的 on-call 班次设计基本沿用 Google SRE 模型:主班 + 副班,主班 SLA 是接到 page 后 10 分钟内 ack;副班作为 backup,主班联系不上时由副班接手。盘中行情时段(09:30-15:00、夜盘 21:00-02:30)的 on-call 比夜班更紧迫,因为故障的客户影响立即可见。节假日排班与国内法定假期强绑定——春节、国庆、五一各有专门排班表;除夕到初三常配双值班,因为这几天市场休市但系统需要做账务对账与数据落库。等保三级环境下的复盘留档由信息安全 + 合规团队主导模板,复盘记录归档到内部 wiki 与合规系统两个位置,留存期通常 3 年以上。

实战中常见的反模式

四条 quant developer 常踩的坑:(1) 收到告警先查代码而不查 dashboard——dashboard 通常 30 秒就能说明问题,read code 要十几分钟;(2) 复盘只列一个根因——这是单一根因冲动,通常意味着只看到了触发因子而忽略了放大因子与检测延迟因子;(3) action item 没有 owner 与 due date——这是愿望,不是结果;两周后回访会发现没人推进;(4) runbook 写成散文——值班时人是 panic 状态,需要可复制粘贴的命令,不需要解释。本课的 runbook 模板与五阶段流程就是这四条反模式的解药。

模块收尾

至此本模块四课全部完成。L1 把 3.6.5 capstone 的服务装进结构化 JSON 日志层;L2 加上 Prometheus 指标 + Grafana dashboard + Alertmanager 告警;L3 加上 OpenTelemetry 链路追踪 + Loki 日志聚合 + 三支柱跨 trace_id 关联 + SLI/SLO/错误预算;L4 配上完整 runbook + 合成事故演练 + 五阶段事故响应 + 无责复盘。你现在能回答凌晨被叫醒时的所有四个问题:『健康吗?延迟在哪?哪里变了?怎么恢复?』全靠 dashboard、trace、log、runbook,不靠 ssh + tail -f。