一、容错基础:交易系统为什么不能「挂」?

大家好,我是你们的讲师。今天咱们聊聊容错——这个词听起来挺高大上,其实说白了就是:系统出问题了,你别给我停

我入行那会儿,带我的老工程师说过一句话,我到现在还记得:「交易系统不是跑得快就行,关键是别死。」 嗯,这话糙理不糙。

1.1 什么是容错?

容错(Fault Tolerance),指的是系统在部分组件发生故障时,仍然能够继续正常运行的能力。注意,这里说的是「继续运行」,不是「优雅退出」——交易系统里,优雅退出往往意味着亏钱。

我个人习惯把容错分成两个层次:

  • 故障检测:你得知道哪里坏了
  • 故障恢复:坏了之后怎么补救

举个例子,你开车爆胎了。容错不是让你不爆胎,而是爆胎后你还能靠备胎开到修理厂。交易系统也一样——网络断了、机器挂了、数据乱了,你得有「备胎」顶上。

核心观点: 容错 ≠ 不出错,而是出错后系统依然可用。

1.2 为什么交易系统必须容错?

这个问题我问过不少新人,有人回答「怕亏钱」,有人回答「怕被投诉」。都对,但不够本质。

我给你们讲个真实案例。几年前我参与过一个期货高频系统的重构,上线第一天,凌晨2点,数据库主库磁盘满了。按理说应该切到备库,但备库的同步延迟配置有问题,切过去数据差了3秒。结果呢?第二天开盘,策略基于错误数据下了两笔废单,直接亏了十几万。

为什么会这样?因为系统设计时只考虑了「主库挂了怎么办」,没考虑「主库挂了但备库数据不一致怎么办」。这就是容错设计不完整的典型。

交易系统对容错的要求,说白了就三点:

  1. 资金安全:错单、重复下单、漏单,哪个都赔不起
  2. 业务连续性:行情来了你宕机,客户直接换券商
  3. 监管合规:很多交易所要求系统必须有灾备和恢复能力
我的经验: 做容错设计时,别只盯着「技术故障」,更要考虑「数据不一致」——后者往往更隐蔽,破坏力也更大。

1.3 常见的故障类型

咱们把故障分个类。我习惯用一张图来概括:

交易系统常见故障类型 🌐 网络中断 • 交易所行情链路断开 • 订单网关连接超时 • 内部服务间通信失败 💻 硬件故障 • 服务器宕机/重启 • 磁盘损坏/读写失败 • 内存ECC报错 🐛 软件崩溃 • 策略进程OOM被kill • 数据库连接池耗尽 • 死锁导致服务无响应 📊 数据不一致 • 主备库数据不同步 • 行情序列号跳变 • 订单状态与资金对不上

下面我逐个展开说说,每个类型我都踩过坑。

1.3.1 网络中断

这是交易系统里最频繁的故障,没有之一。我经历过最夸张的一次,交易所的行情网关因为光缆被施工队挖断,整整断了40分钟。那40分钟里,我们的系统还在不断重连、超时、再重连——幸好有熔断机制,不然网关层直接被打挂。

网络中断的典型场景:

  • 行情链路断:收不到最新报价,策略还在用旧数据算
  • 交易链路断:订单发不出去,或者发了不知道成交没
  • 内部网络抖:微服务之间调用超时,引发级联故障
避坑指南: 我曾经以为「重试」能解决一切网络问题。直到有一次,重试逻辑写成了死循环,把交易所的网关打限流了。记住:重试必须有退避策略,而且要有最大次数限制

1.3.2 硬件故障

硬件故障其实比软件故障好处理,因为它的表现通常很「诚实」——坏了就是坏了,不会跟你玩花样。但问题是,硬件故障往往发生在最不该发生的时候。

我记得有一次,一台跑核心撮合服务的服务器,凌晨3点内存报错。监控系统自动把流量切到了备机,但备机因为之前没跑过全量数据,内存里缺了部分订单簿快照。结果开盘后,有几笔订单的成交价算错了。

硬件故障的几个典型:

故障类型 表现 影响
磁盘故障 读写超时、I/O错误 日志写不进去,行情落盘失败
内存故障 ECC报错、进程被OOM Killer 策略进程突然消失
网卡故障 丢包率飙升、延迟抖动 订单超时、重连风暴
电源故障 服务器直接断电 全盘停服

1.3.3 软件崩溃

软件崩溃是最让人头疼的,因为它往往不是「一下子全挂」,而是「慢慢变慢,然后突然死掉」。我见过太多因为内存泄漏导致OOM的案例了。

举个例子,一个行情处理程序,每收到一笔行情就new一个对象,但忘记释放了。跑了一天,内存从2G涨到8G,然后被系统kill。重启后继续涨,继续kill。运维大哥一晚上被报警短信吵醒5次。

软件崩溃的常见原因:

  • 内存泄漏:对象只增不减,GC都救不了
  • 死锁:两个线程互相等对方释放锁
  • 资源耗尽:文件句柄、数据库连接、线程池全部占满
  • 未捕获异常:一个空指针直接让主线程退出
我的习惯: 所有核心服务必须配置「自动重启+健康检查」。进程挂了不要紧,关键是挂了之后能自己拉起来,并且拉起来后能快速恢复状态。

1.3.4 数据不一致

这是最隐蔽、最危险的故障类型。网络断了你能看到告警,硬件坏了你能看到红灯,但数据不一致——它可能安安静静地运行好几天,直到对账时才发现亏了几十万。

我亲身经历过一个案例:我们的订单系统和资金系统分别用了两个数据库,订单库记录了「已成交」,但资金库因为一个事务回滚,没扣钱。结果客户提现时发现账户里多了钱,等我们追回来的时候,人家已经转走了。

数据不一致的典型场景:

  • 主备不同步:主库写成功了,备库还没同步就切过去了
  • 分布式事务失败:A服务成功了,B服务回滚了
  • 缓存与数据库不一致:缓存里是旧数据,数据库是新数据
  • 行情序列号乱序:收到的行情不是按时间顺序来的
重要提醒: 数据不一致的修复成本,往往比系统宕机还高。宕机最多损失几分钟的交易时间,数据不一致可能要花几天甚至几周去对账、回滚、修复。

1.4 小结

这一章咱们把容错的基础概念和常见故障类型过了一遍。说白了,容错就是给系统买保险——你希望它永远不出事,但万一出了事,你得有预案。

我个人觉得,做容错设计最忌讳的就是「想当然」。你以为主库挂了备库能顶上,结果备库数据不对;你以为重试能解决网络问题,结果重试把系统打崩了。每一个「我以为」背后,都可能是一个线上事故。

下一章开始,咱们会深入具体的容错技术——从心跳检测到熔断降级,从超时控制到数据校验。嗯,到时候我会拿我踩过的坑一个一个给你们讲。


专注资料整理