一、撮合引擎概述
什么是撮合引擎
撮合引擎,说白了就是交易所的「心脏」。
你想想看,当你在交易软件上点下「买入」按钮的那一刻,背后发生了什么?
你的订单不会直接飞到交易所的数据库里。它会先进入一个排队系统,然后跟所有其他用户的订单进行匹配——谁想买、谁想卖,价格能不能对上,数量够不够。这套完成匹配的系统,就是撮合引擎。
我个人习惯把它比作「红娘」。买方和卖方互不认识,撮合引擎负责牵线搭桥。价格谈拢了,数量对上了,一笔交易就成了。
核心定义:撮合引擎是一种实时处理订单、执行价格优先/时间优先规则、生成成交记录的软件系统。它是交易所最核心的组件,没有之一。
撮合引擎在交易所中的位置
一个完整的交易所系统,通常长这样:
| 层级 | 组件 | 说明 |
|---|---|---|
| 接入层 | API网关、WebSocket服务 | 接收用户订单,返回成交结果 |
| 业务层 | 账户系统、风控系统 | 检查余额、验证权限 |
| 核心层 | 撮合引擎 | 订单匹配、生成成交 |
| 数据层 | 数据库、消息队列 | 持久化订单、推送行情 |
| 清算层 | 结算系统 | 资金划转、持仓更新 |
看到没?撮合引擎在正中间。它前面连着用户请求,后面连着资金清算。一旦它出问题,整个交易所就瘫痪了。
我在项目中遇到过一件事:有一次撮合引擎的延迟从微秒级飙升到毫秒级,结果整个交易系统的订单堆积如山,用户投诉电话被打爆。嗯,从那以后我明白了——撮合引擎的稳定性,就是交易所的生命线。
核心功能
撮合引擎到底干了哪些活?我总结为四个字:收、排、配、发。
- 收:接收订单。从API网关拿到用户的买卖请求。
- 排:订单排队。按照价格优先、时间优先的原则,把订单塞进订单簿。
- 配:匹配成交。检查当前订单能否与对手盘成交,能的话就生成交易记录。
- 发:发送结果。把成交信息推送给用户,同时通知清算系统更新账户。
听起来简单?其实每个环节都有坑。
举个例子,「价格优先」好理解——出价高的买家优先成交。但「时间优先」呢?如果两个买家出价一样,谁先到谁先得。这个「先到」怎么判断?毫秒级的时间戳够不够?
我曾经踩过一个坑:系统里用的时间戳精度不够,导致两个同时到达的订单被错误排序。结果用户投诉说「我明明先下单,凭什么别人成交了?」后来我们改成了纳秒级时间戳 + 硬件时钟同步,才彻底解决。
避坑指南:我曾经以为时间戳精度越高越好,后来发现还要考虑时钟漂移。建议用单调递增的序列号代替时间戳做排序依据,这样更可靠。
性能指标
衡量一个撮合引擎好不好,看三个指标就够了:
| 指标 | 含义 | 行业标准 |
|---|---|---|
| 吞吐量(TPS) | 每秒能处理多少笔订单 | 大型交易所要求 > 100万 TPS |
| 延迟(Latency) | 从收到订单到返回结果的时间 | 核心延迟 < 100微秒 |
| 公平性(Fairness) | 订单是否按规则被公平处理 | 无锁设计 + 严格FIFO |
你可能会问:为什么延迟要控制在微秒级?
因为高频交易的世界里,1毫秒的延迟就意味着几百万的损失。我见过一些团队用Python写撮合引擎,结果延迟跑到几十毫秒——说实话,这种系统只能做做演示,真上生产环境会被市场吃掉。
注意:不要盲目追求高TPS而牺牲公平性。有些系统为了性能,用了「批量处理」的方式——攒够1000个订单再一起撮合。这样做TPS上去了,但先到的订单反而要等后面的订单凑齐才能成交,这严重违反了时间优先原则。
撮合引擎的两种架构
我见过两种主流的撮合引擎架构:
- 单线程模型:所有订单在一个线程里串行处理。优点是简单、无锁、公平性好。缺点是CPU利用率上不去。
- 多线程模型:按交易对分片,每个分片一个线程。优点是能利用多核CPU。缺点是跨分片的订单处理复杂。
我个人更倾向于单线程模型。为什么?因为撮合引擎的瓶颈通常不在CPU,而在内存访问和锁竞争。单线程模型天然避免了锁的问题,而且代码逻辑清晰,不容易出bug。
你想想看,一个撮合引擎如果出了bug,导致成交价格算错了——那可不是闹着玩的。用户的钱会直接损失,交易所的信誉也会崩塌。
我的建议:如果你从零开始写撮合引擎,先用单线程模型。等业务量上来了,再考虑按交易对分片做多线程。别一开始就搞复杂架构,容易翻车。
小结
这一章我们聊了撮合引擎是什么、它在交易所中的位置、核心功能以及性能指标。
说白了,撮合引擎就是交易所的「心脏」。它要快、要稳、要公平。任何一个环节出问题,都会直接影响用户的交易体验和资金安全。
下一章,我会带你深入订单簿的内部结构——看看那些买卖订单到底是怎么排队的。到时候我会分享一个我亲手写过的订单簿实现,里面有坑也有经验,希望对你有帮助。
公众号:蓝海资料掘金营,微信deep3321