重启不丢上下文:交易系统的状态持久化
交易系统最怕两件事:亏钱,和重启。
亏钱还能靠风控拦着。重启是物理定律——服务器总要维护,进程总要更新。问题不在于能不能重启,在于重启后策略能不能立刻恢复到重启前的状态。
为什么重启是个问题
假设你有一个趋势追踪策略,它维护了以下状态:
- BOCPD 变点检测的 history buffer(需要数百个数据点)
- 信号服务的缓存结果(微趋势分数、资金费率、L 信号)
- 当前持仓的入场价、止损线、止盈线
重启后:
- BOCPD buffer 清空 → 需要等数百个新数据点 → 数十分钟的真空期
- 信号服务缓存清空 → 需要重新调用 API → 数分钟的延迟
- 止损/止盈丢失 → 持仓裸露无保护,直到重新计算
重启一次 = 策略失明数十分钟。 在这期间,任何行情变化都不会被响应。
持久化什么
不是全量持久化。分优先级:
P0(重启后必须恢复)
- BOCPD tracker 的 run-length distribution → 没有它,变点检测要重新预热
- 信号服务的缓存分数 → 没有它,开仓信号要等新数据
- 当前持仓的退出条件(止损/止盈)→ 重启后不能丢,否则持仓裸奔
P1(重启后可以慢慢恢复)
- 历史信号日志 → 丢了不影响当前决策
- 统计计数器 → 可以重新累加
P2(不持久化)
- 实时行情快照 → 重启后 WS 会自动推送最新的
- 临时计算结果 → 可以重新算
怎么持久化
用 Redis 做状态存储,RDB 快照 + AOF 双保险。关键设计:
策略启动
│
├─ 检查 Redis 是否有持久化状态?
│ ├─ 有 → 加载状态,跳过预热
│ └─ 无 → 进入预热模式
│
└─ 运行中每 N 秒 checkpoint 一次状态到 Redis
不是每次状态变化都写,那样 Redis 会被写炸。是定时 checkpoint——即使丢几秒的状态,也比丢全部重新预热强。
元结构映射:广告系统的索引持久化
这和广告索引的持久化逻辑一致:
| 概念 | 广告索引 | 交易状态 |
|---|---|---|
| 全量持久化 | 索引定期 dump 到磁盘 | Redis RDB 快照 |
| 增量恢复 | 重放 binlog | Redis AOF 增量 |
| 重启恢复 | 加载 dump + 重放 binlog → 秒级恢复 | 加载快照 + 上次 checkpoint 后数据 → 跳过预热 |
| 预热时间 | 索引重建数十分钟 | BOCPD 预热数十分钟 |
本质相同:重启后不是从零开始,而是从上次的 checkpoint 开始追增量。
一句话
服务重启不可怕,可怕的是重启后策略失明数十分钟。持久化 BOCPD tracker 和退出条件——这两样丢了是真的会亏钱的。