一、撮合队列基础:从排队说起

大家好,我是老张。今天咱们聊聊撮合队列。

先问个问题:你去银行办业务,是不是得取号排队?前面的人办完了,才轮到你。这个「排队」的过程,其实就是队列的核心思想。

金融交易系统里的撮合队列,说白了就是给买卖订单排队的机制。只不过这个队伍排得特别快——毫秒级别,而且规则极其严格。

什么是撮合队列

撮合队列,是交易引擎用来管理订单的核心数据结构。它负责接收买卖双方的订单,按照价格优先、时间优先的原则进行匹配。

我打个比方:

  • 买方说「我出10块钱买1股」
  • 卖方说「我9块9卖1股」
  • 撮合队列一看:买方出价高于卖方要价,成交!

就这么简单。但实际系统里,每秒可能有几万甚至几十万笔这样的订单涌进来。怎么保证不丢单、不乱序、不冲突?这就是撮合队列要解决的问题。

核心要点:撮合队列的本质是一个「有序的等待队列」,它保证了所有订单都能按照公平的规则被处理。

撮合队列在金融交易系统中的作用

我做过几个交易所的后端系统,说实话,撮合队列是整个系统的「心脏」。它干三件事:

  1. 接收订单:从客户端、API网关接收买卖请求
  2. 排队等待:按价格、时间排序,形成有序队列
  3. 执行撮合:找到匹配的买卖双方,完成交易

你想想看,如果没有撮合队列,会发生什么?

比如两个买家同时出价10块买同一只股票,系统该先处理谁?如果没有队列,结果就是乱套——有人插队、有人被漏掉、有人投诉不公平。

注意:我曾经在一个项目中遇到过,因为队列设计不合理,导致高并发时订单丢失。排查了三天才发现是队列溢出导致的。从那以后,我对队列的容量和背压机制特别敏感。

核心概念:订单簿

订单簿,是撮合队列的「灵魂」。它记录了当前所有未成交的买卖订单。

订单簿分两边:

  • 买单队列:所有想买的人,按价格从高到低排
  • 卖单队列:所有想卖的人,按价格从低到高排

为什么这么排?因为买方当然希望价格越低越好,但为了抢到货,愿意出高价的人排前面。卖方正好相反,想卖高价,但为了尽快出手,愿意低价卖的人排前面。

嗯,这里要注意:价格优先是第一原则。同样价格,才看谁先来。

核心概念:买卖盘口

买卖盘口,就是订单簿的「快照」。它展示了当前市场上最好的买价和卖价。

举个例子:

买盘(Bid) 价格 卖盘(Ask)
100股 @ 10.01 10.01 200股 @ 10.02
300股 @ 10.00 10.00 150股 @ 10.03
500股 @ 9.99 9.99 400股 @ 10.04

这个表格里:

  • 最高买价是10.01,有100股想买
  • 最低卖价是10.02,有200股想卖
  • 买卖价差是0.01元

如果这时候有人出价10.02买,或者10.01卖,就能立刻成交。这就是盘口的意义——告诉你当前市场最真实的供需情况。

个人经验:我建议你在设计盘口数据结构时,用红黑树或者跳表。因为盘口需要频繁地插入、删除、查询最优价格。数组和链表在这种场景下性能太差了。我曾经用链表实现过,结果压测到1万笔/秒就扛不住了,换成跳表后直接干到10万+。

知识体系图

下面这张图展示了撮合队列的核心知识结构:

撮合队列 接收订单 排队等待 执行撮合 订单簿(Order Book) 价格优先 + 时间优先 买卖盘口(Bid/Ask) 核心原则:价格优先 > 时间优先 所有订单必须排队,不允许插队,保证公平性

实际项目中的坑

讲几个我踩过的坑:

  • 队列溢出:高并发时订单量暴增,队列满了怎么办?我建议用有界队列 + 拒绝策略,而不是无界队列。无界队列会把内存撑爆。
  • 锁竞争:撮合队列是共享资源,多线程访问时锁竞争严重。我后来改用无锁队列(Disruptor),性能提升了3倍。
  • 持久化:订单进来后要不要先落盘?我的经验是:先写日志再处理。万一系统崩溃,可以从日志恢复。

避坑指南:我曾经因为没做订单去重,导致同一笔订单被撮合了两次。后果很严重——客户多买了股票,我们赔了不少钱。从那以后,我坚持在队列入口做幂等性校验。

小结

撮合队列是交易系统的基石。它负责接收订单、排队等待、执行撮合。核心概念包括订单簿和买卖盘口。

订单簿记录了所有未成交的订单,买卖盘口展示了当前最优的买卖价格。设计时要注意队列容量、锁竞争、持久化和幂等性。

说白了,撮合队列就是一个「公平的排队机制」。没有它,金融市场就乱套了。


公众号:蓝海资料掘金营,微信deep3321