资讯动态

实时行情系统架构设计:协议选型、数据源与高可用实战

发布时间:2026/9/10 15:31:06 来源:尧图企业网站定制
做行情系统这行久了最常被问的一句话就是你们那实时行情到底有多实时这个问题听起来简单背后牵出来的链路却很长从交易所或数据源发出第一笔行情到用户屏幕上那个数字跳动中间经过协议解析、数据路由、多级缓存、推送分发任何一个环节慢了几毫秒行情就不实时了。更麻烦的是行情系统不只是快就行它还得稳——不能断、不能错、不能乱遇到上游抖动还要能扛住。这篇就从协议选择、数据源选型、高可用架构这三个主战场把我做实时行情系统这些年踩过的坑、沉淀下来的设计思路完整拆一遍。这篇内容适合三类人看一是准备从零搭建行情服务的后端工程师二是已经在维护行情系统但总觉得能用但不敢大改的同学三是想搞清楚行情数据到底怎么从源头流到业务方的架构师。不论你是做股票、期货还是数字资产的实时行情底层思路是相通的我会把通用的部分讲透再把特定场景下的取舍一并说清。1. 行情系统到底在解决什么问题1.1 行情系统的定位与核心指标行情系统在技术圈里是块小而精的硬骨头。小是因为它承接的消息类型很集中——无非是逐笔成交、盘口快照、K线、涨跌停等几种精是因为它同时踩中三个极端数据量大、延迟敏感、可用性要求严苛。这三者互相拉扯设计上稍有不慎就会顾此失彼。判断一个行情系统好不好核心指标其实就是三个端到端延迟从数据源产生行情到终端收到行情的时间差通常用xx毫秒内送达来衡量。这个指标直接决定了行情实时的程度。吞吐能力单位时间内能处理的行情消息条数。行情系统在开盘和收盘时段往往会有瞬时洪峰吞吐设计不足就直接丢消息。可用性系统在一段时间内不中断服务的概率。行情是典型的高频依赖型服务断个几十秒下游业务方比如交易策略、风控系统就会出大问题。这三角色里延迟和吞吐天然冲突吞吐和可用性互相制约。架构的功夫就在于怎么权衡而不是盲目追求某个单点极限。1.2 实时行情链路的基本盘不管业务多复杂行情数据从源头到终端基本都要走这样一条链路数据源 → 接入网关 → 校验清洗 → 路由分发 → 业务适配 → 终端推送每个环节再往下拆都会有一堆细节。接入网关负责和各种外部数据源建立连接实时收流并解析校验清洗环节要做完整性检查、时间戳校准和异常值剔除路由分发决定这条行情消息应该送给哪个业务模块业务适配则是把统一的内部格式转成各个下游需要的形态终端推送则是通过WebSocket、TCP长连接等方式把行情推给最终用户。我在实际设计中一直坚持一个原则内部统一中间格式。不管上游是二进制协议、Protobuf还是JSON进了系统一律转成统一的内部结构体下游各取所需。这一步虽然会带来一点点解析延迟但换来的却是维护性的质变——否则每接一个新数据源下游每个模块都要跟着改一遍。1.3 为什么协议、数据源和架构要绑在一起考虑很多团队做行情系统容易陷入一个误区协议选型归选型、数据源接入归接入、高可用架构归架构各自分开做最后拼起来发现带不动。我个人的经验是这三者必须放到一张图上去设计因为它们的耦合点非常深。协议选择直接决定接入层的复杂度也严重影响高可用架构的容错策略。比如你选了WebSocket那心跳和断线重连天然就有一套标准解法如果你用UDP组播做低延迟分发那乱序、丢包就得在应用层自己想办法架构里必须多设计一个状态同步兜底的环节。数据源选型则决定了接入层的数量、多源切换的复杂度以及行情数据的质量上限——源头如果经常延迟、缺数架构再稳也没用。所以题目里说的从协议到架构再到数据源并不是想先讲哪个就先讲哪个而是一环扣一环的依赖关系。2. 协议选择先别急着上WebSocket把权衡想清楚2.1 协议选型的底层逻辑行情协议选型是我每次做新项目都会重新过一遍的决定。市面上可选的无非是WebSocket、自定义TCP二进制协议、UDP组播、QUIC这几类但真要按照实时行情的场景去套每一类都有自己的短板。选协议的时候我一般只问三个问题允许的端到端延迟是多少如果业务允许100ms以上那TCP阵营随便选如果要求到终端20ms以内TCP的拥塞控制、队头阻塞就成了绕不开的坎。数据连接的规模多大千级连接的推送跟百万级连接的推送协议层面的考量完全不同。网络环境可控吗如果终端分散在公网、跨地域、移动网络和机房内部独立组网的低延迟链路能用的协议栈也不一样。把这三个问题回答完协议选型的大方向基本就出来了。2.2 WebSocket与自定义TCP二进制协议通用性 vs 性能WebSocket是很多团队做实时推送时的第一反应因为浏览器原生支持、调试方便、周边生态好。但它在行情场景下有个绕不开的痛点——传输效率偏低。WebSocket天然以文本帧为主实用中很多团队又偷懒直接用JSON传行情数据我想想都心疼那带宽。行情是高频小消息单条快照可能就几百字节但盘口变动时一秒几十笔折算下来数据量很可观。用WebSocket推行情最大的代价还不是带宽而是解析开销——JSON解析本身就是CPU密集操作在高吞吐场景下会成为瓶颈。自定义TCP二进制协议则在这一点上优势明显。定一个紧凑的报文结构头几个字节放消息号、时间戳、序列号后面按固定格式排列买卖盘口数据。解析就是内存拷贝连反序列化都不用性能差距能到数倍。代价是调试麻烦没法直接在浏览器里看还得做测试工具。但如果你的行情是服务内部系统而不是浏览器页面我强烈建议走自定义二进制协议收益大到值得多写那点工具代码。2.3 UDP组播与QUIC低延迟到底怎么压出来再往上走就是延迟敏感型机构玩家关注的地带。如果你是要服务于本地机房内的量化策略程序化交易链路短、网络自治可控UDP组播几乎是标准答案。UDP没有三次握手、没有拥塞控制、没有队列调度天然适合一对多的行情广播。但代价也很大它不可靠、会乱序、会丢包。所以使用UDP组播的行情系统应用层必须自己补一套可靠传输逻辑——序列号比对、丢包重发、快照同步。QUIC是近几年新兴的方案它基于UDP实现可靠传输同时解决了TCP的队头阻塞问题还有0-RTT连接建立能力。在我实测的场景里QUIC对弱网环境下的行情推送提升非常明显尤其是移动端、跨地域的长链路延迟抖动比TCP小很多。缺点是目前中间件支持和运维工具相对少团队要有一定技术积累才玩得转。但如果你做的是公网行情服务且延迟要求比较高QUIC值得认真考虑。2.4 协议选型的实战对照表为了方便对比我整理了几种方案的适用场景和注意点协议方案延迟量级吞吐上限可靠性适用场景主要坑点WebSocket JSON中等中等TCP可靠浏览器端、快速实现解析开销大、带宽浪费WebSocket Protobuf中等偏低中等偏高TCP可靠浏览器端服务端需管理schema兼容自定义TCP二进制低高TCP可靠服务端内部对接调试成本高UDP组播极低极高不可靠需自建恢复局域网内低延迟分发需要精心设计恢复机制QUIC低高可靠公网、移动端、跨地域运维工具链不成熟从我个人的项目经验来排优先级内部链路默认用UDP组播或自定义二进制TCP外部公网推送优先考虑QUIC只有交付给浏览器端或对外快速迭代的功能才会落到WebSocket上。这个层级划分省了我大量精力也避免了反复改协议栈的尴尬。3. 数据源选型源头脏了下游全白干3.1 行情数据源有哪些类型行情数据的来源一般来说分几类官方交易所/核心撮合引擎直连接口延迟最低、数据最权威但接入门槛高、对接成本大。第三方聚合数据服务商把多家行情源聚合好再统一输出接入简单、成本可控但会有额外一跳延迟。商业数据终端/代理源比如做一些落盘、转发的中间商适合做冷备或者容灾。爬虫抓取的公开页面数据这个基本只适合做低频率、非实时类的兜底延迟高且不稳定。在我做过的项目里数据源从来不是越多越好。核心一手源一定保留一个这是基准然后根据业务量级再配置一个或两个备用源用于容灾和质量比对。3.2 数据源质量评估的四个维度选数据源不能只看报价和宣传一定要自己动手做质量评估。我评估一个数据源通常从四个维度打分及时性从源头事件产生到数据源发出行情的时间差这个要实际对比两个数据源的到达时间来检验。完整性是否频繁缺消息、缺字段、缺K线周期。有些源会在盘中时段故意降级得盯住。稳定性断连率、重连耗时、故障时长。这里不光看服务商给的SLA更要看真实运行中的表现。准确性行情数据有没有错价、乱序、跳跃。这一项要拿两个独立源做交叉验证单靠一个源根本测不出来。这四个维度可以用一张评分表来量化低于及格线的一票否决不能因为价格便宜就妥协——行情数据一旦错漏引发的连锁问题远大于省下的那点成本。3.3 多源融合与主备切换策略多源不是摆设而是要真的派上用场。我一般把数据源分为主源和备源主源负责日常生产备源持续在线保持热同步。切换策略上我坚持两个原则第一主备切换不能看单一指标。不能因为主源断连几秒就立刻切换容易造成抖动误判。要设置一个判定窗口比如连续3次心跳失败且超过5秒才触发切换这样既能在真故障时快速响应又不会因为偶发抖动而频繁割接。第二切换流程要尽量自动化但要留人工兜底。自动化切换能解决90%的场景剩下的10%比如数据源静默出错但心跳正常必须靠监控告警和人工介入来处理。我之前遇到过一次主源数据延迟了十几秒但连接一直没断自动化切换完全没触发最后靠监控比对发现异常才切走的。这个教训让我后来在切换逻辑里额外加了一条数据新鲜度检测不只看连接是否活着还要看数据是否在持续前进。3.4 数据源接入的实测经验接入不同数据源的时候我最常踩的坑有两个。第一个是多源时间戳口径不一致。A源给的是本地网关时间B源给的是事件时间C源给的是落盘时间三个源的数据在比对时就会错位。所以接入时我要求在网关层统一校准为同一时区的UTC时间并保留原始时间戳和接入时间戳两个字段后续排查问题会省大事。第二个坑是数据源限流策略不透明。有些第三方源会在行情洪峰时偷偷降级——比如原来每100ms推一条快照盘中变成每500ms推一条。这种降级不会体现在连接层面只有拿另一个源做对比才能发现。我现在的做法是在接入网关层对每个源记录期望消息数/实际消息数的比值一旦这个比值偏离正常范围立刻触发告警把隐藏降级打回原形。4. 高可用架构从单点到可容灾的演进路径4.1 高可用要防的是哪几类故障行情系统的高可用设计本质上是在对抗四类故障进程级故障OOM、崩溃、死锁、节点级故障宕机、断电、机房级故障光缆中断、区域性网络异常、上游故障数据源断连、协议异常。每一类故障的防护手段不同但整体目标一致任何一个环节出问题都不能让用户感受到行情中断。很多团队做到节点级故障的冗余就觉得高可用完成了但真实生产中最致命的往往是机房级故障——光缆被挖断这种事虽然概率低一旦发生就是全量不可用。如果行情服务是交易系统的眼睛眼瞎哪怕十分钟都是不可接受的。4.2 分层集群接入层、汇聚层、分发层我常用的高可用架构是三层集群模式接入层负责和外部数据源建立连接、接入解析。这一层必须是多节点无状态的任意一台挂掉其他节点都能接管连接。数据源侧要有负载均衡或者抢占机制避免多台接入节点同时处理同一份数据造成重复。汇聚层负责去重、排序、清洗、合成完整订单簿和K线。这一层通常采用主备模式备节点实时同步状态主节点故障时秒级切换。这里最难的是保持状态一致——比如当前订单簿的深度快照主备之间需要持续同步快照和增量日志。分发层面向下游业务方负责把清洗后的行情推送给各个消费端。这一层要有水平扩展能力连接的消费者多了就加节点。它本身不持有复杂状态所以扩展是最简单的。三层分离最大的好处是能独立扩缩容。开盘时用户量暴增分发层加机器就行接入的数据源数量多了接入层单独扩容汇聚层则保持小而精保证一致性。4.3 故障切换与降级策略故障切换之外降级策略也是高可用里很重要的一环。行情系统的降级不像普通业务那样直接限流就完了它有一套典型的降级阶梯第一阶段停止推送不重要的衍生数据比如逐笔成交明细保留核心快照。第二阶段降低推送频率比如原本100ms推一次的快照改成500ms推一次。第三阶段停止增量推送只提供手动查询最新快照的能力。这个阶梯的好处是每一级降级都在换取系统的存活能力让核心用户比如交易员、风控系统始终能看到最新行情只是刷新频率降低了而不是直接黑屏。降级触发条件和恢复条件要写清楚并且要经过演练验证——我见过不少系统在故障演练中因为降级恢复逻辑没测过故障结束后服务一直留在降级状态那反而更麻烦。4.4 延迟与可用性的平衡做高可用架构时最容易犯的错是过度追求万无一失而牺牲性能。比如每个环节都做同步双写、每次转发都做多副本确认延迟会直线上升。我的经验是在实时行情这个场景里可靠性和低延迟之间要有一个清晰的分层热点路径低延迟冷备路径重保障。热点路径上数据直接在主链路上转发尽量不做多次确认冷备路径则用异步的方式持续同步状态保证故障时可以接管。这个设计思路的关键词是冗余但不阻塞体现在实际操作中就是同一份行情数据在主链路上走得很轻快在备份链路里走得慢一点没关系只要状态最终对齐即可。这样当主节点故障时备节点接管后能在一个较短的窗口内补上数据缺口既保证了可用性又把主链路的延迟压到了最低。5. 常见问题与排查技巧实录5.1 延迟抖动排查先查链路水位再查应用逻辑行情系统出现延迟波动很多人第一反应是去查代码其实绝大多数延迟问题出在网络链路和中间件水位上。我通常按这个顺序排查先看从数据源到接入网关的链路时延——用两个独立源对比到达时间如果A源比B源慢了30ms以上问题大概率在上游不在自己系统里。再看接入层到汇聚层、汇聚层到分发层之间的队列堆积量。行情系统每个环节都有缓冲队列正常情况下队列几乎是空的一旦出现堆积就说明下游消费速度跟不上上游生产速度这时候要先扩容下游而不是优化代码。最后才看应用逻辑——GC停顿、锁竞争、磁盘IO都会造成延迟毛刺。我遇到过最隐蔽的一类问题是JVM的GC日志在高峰期写盘导致停顿移动日志目录后延迟掉了15ms。5.2 数据乱序与重复用序列号兜底多路数据源同时接入后乱序和重复几乎是必然的。同一个合约的快照可能先从B源到了A源的后到如果直接把消息按到达顺序推出去终端就会看到价格来回跳。我的做法是在汇聚层为每一条行情消息分配一个全局递增序列号并维护一个最新已推送序列号水位。消息来了先比对序列号小于水位的直接丢弃重复消息大于水位但中间有缺号的就等待一个极短的重排窗口比如3毫秒补不上再根据策略选择跳过或者申请重发。这个窗口要选得很谨慎太短会有乱序遗漏太长则会增加端到端延迟。我在实际项目中用过2-5毫秒基本能覆盖绝大多数网络乱序场景。5.3 重连风暴给断线重连加个缓冲垫行情系统跟数据源的连接一旦不稳定最怕的不是断线本身而是重连风暴——断线后所有接入节点同时重连把数据源的连接数瞬间打满导致更严重的拒绝服务。我采取的方案是给每个接入节点配置不同的重连初始退避值并叠加随机抖动。比如节点A初始退避200ms节点B是500ms节点C是1s每次重连失败退避加倍最大到30秒。这样即使上游故障恢复接入层的重连请求也会错峰不会形成冲击。这套机制我在一个事故复盘后加上去的从那以后再没出现过重连风暴的问题。5.4 多源切换时的数据跳变处理主备数据源切换时最常接到客服反馈的问题是价格突然跳了一下是不是系统出bug了这里面的原因多半不是bug而是两个数据源的快照本来就有细微差异——它们的聚合深度、更新频率、甚至价格精度都可能不同切换后终端的盘口就会出现跳变。我的处理办法是在切换时给终端下发一个数据源切换提示事件同时做一次全量快照同步而不是继续流式地推送增量。这样终端收到提示后会清空旧的盘口数据以新的快照重建订单簿用户看到的效果是刷新了一次而不是价格乱了。这个设计虽然看起来小而细但真正决定了一个行情系统在运维层面是不是老练。写在最后的实操心得行情系统做到后面拼的往往不是某个炫技的架构而是对细节的敬畏和管理运维的成熟度。三个体会分享给同行第一协议选型要做五年后还够不够用的判断不要贪图一时的开发速度。协议一旦上线改造成本极高宁可前期多花一周做压测和场景推演。第二多源设计不是简单的备胎逻辑要日常就用起来做实时比对、互为主备否则关键时刻根本不敢切。我在项目里就是让两个源长期并行跑任何一方的异常都能在30秒内被监控发现。第三高可用不是配置出来的是演练出来的。每年至少要安排两次故障演练人为断数据源、杀节点、模拟机房故障看看系统到底能不能自己扛住。没演练过的高可用配置都只能算纸上谈兵。最后分享一个小技巧对于行情这种高吞吐低延迟的业务监控系统本身也要做性能优化不能因为监控产生额外开销。我用过不少方案最终采用的是边缘节点采集 聚合后上报 独立监控链路的模式确保监控只在异常时被高频触发正常情况下几乎不占用主链路资源。这套手法让我的行情系统在持续运行中一直保持稳字当头希望对你也有参考价值。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价