实时行情系统的坑,我踩了不止一次。前几年给一套交易辅助平台做行情模块的时候,团队里每个人对“实时”两个字都有自己的理解:做后台的觉得 500 毫秒也叫实时,做策略的恨不得每笔成交都在 1 毫秒内落地,做运维的又担心链路一抖就雪崩。那段时间开会讨论最多的就是三个问题:接入用什么协议,架构怎么做成高可用,数据源到底听谁的。这篇不打算写成教科书式的架构说明,主要分享我们在协议选择、高可用链路、数据源选型这三件事上的真实取舍、踩过的坑,以及一些事后复盘出来的设计原则。准备搭建行情系统或者正在改造行情链路的团队,可以参考一下。
1. 动手前先把“实时”变成一组可验证的数字
很多人一上来就开始聊 FIX、聊 UDP 组播、聊 Kafka,但我发现真正的问题往往不是技术选型,而是压根没定义清楚“实时”的验收标准。没有量化目标,所有方案都只是在打嘴仗。
1.1 延迟预算:从哪里开始计时,到哪一步截止
我当时的第一个动作,是让所有人把“实时”落到一条时间轴上:从行情源发出数据、到接入网关收到、再到内部处理后推给下游应用,到底哪一段算延迟?如果只说“全链路要快”,这句话是没有办法指导设计的。
我们最终把延迟预算拆成了三段:上游网络延迟、网关和中间件处理延迟、下游应用消费延迟。其中上游网络延迟通常不受自己控制,只能通过拉专线、把服务部署到靠近行情源机房的区域来优化;自己真正能设计的是后面两段。
举个例子,如果业务容忍的端到端延迟是 100 毫秒,而行情源机房到自己服务器的公网链路正常情况下就要 30 毫秒,那留给内部的预算其实只有 70 毫秒。如果网关解析要 20 毫秒、消息总线排队要 20 毫秒、下游业务处理还要 20 毫秒,看起来每段都不多,但合在一起已经逼近上限。一旦出现 GC 停顿或者网络重传,某一段稍微劣化,P99 立刻就会冲出指标。
所以我会建议先把这条链路每一跳的具体耗时上限写出来,能压缩到多少毫秒、每段由哪个团队负责,然后再去讨论用什么协议和架构。否则最后系统上线了,业务方投诉慢,你根本说不清是源头慢、解析慢还是分发慢。
1.2 容量规划:按峰值设计,别按平均值设计
行情流量有个典型特征:峰值瞬间能把平均曲线甩开很多倍。开盘、收盘、重大消息发布的瞬间,事件频率会突然拉高,而且这种突发可能没有任何预兆。
我们当时统计过一段行情回放数据,全天平均每秒可能只有几千个 tick,但某些瞬间能冲到每秒数万笔,最高峰和均值之间的差距经常是几十倍。这里面真正的瓶颈往往不是带宽,而是包率。一条 tick 消息即使只有几百字节,当每秒几万个包砸过来时,服务器的软中断、内核协议栈解析、用户态拷贝都会成为瓶颈。
做容量规划时我习惯按峰值流量再乘上 3 到 5 倍余量来设计。原因很简单:行情系统不能靠“临时扩容”扛住突发,很多情况下流量是在几秒钟内瞬间上去的,弹性扩容根本来不及。如果买机器时按 QPS 均值去算,高峰期大概率会出现网卡丢包或者处理线程堆积。
1.3 故障恢复窗口:高可用不是“永远在线”,而是“多久恢复”
再好的架构也没法保证不出现断连。真正需要定义清楚的是:如果链路断了,你允许业务在多少秒内感知不到异常,链路恢复后能不能补齐缺失的数据。
我们当时给团队定的目标是:正常情况下从行情源收到 tick 到下游业务可见,P99 不超过 30 毫秒;高峰期不允许丢弃 tick;单条链路断线后自动切换到备用链路的窗口控制在 10 秒以内;断线期间累积的增量如果补齐不了,必须在 30 秒内完成一次全量快照重建。
这几个数字看起来不难,但真正落地的时候会发现,很多协议和架构方案在这些条件下是不过关的。有的协议不支持从断点续传,断线后只能重新拉全量;有的消息队列在重连恢复时需要几十分钟的追赶,根本无法满足 30 秒重建的要求。所以,在写第一行代码之前先把这些硬指标定下来,后面每一步的取舍都会有判断依据。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 接入协议选型:别把“看起来很专业”当成最重要的标准
协议选择是实时行情系统里最容易引发争论的环节。做量化的人大概率会告诉你必须用 FASTER 的二进制协议,做 Web 的人会告诉你 WebSocket 够用了,做传统集成的可能坚持要用 FIX。这些说法在特定语境下都成立,但脱离场景谈协议就是耍流氓。
