撮合系统
模块与职责
源码模块为 coinex-match,实现位于 matching-provider/src/main/java/com/exch/matching。撮合处理并非只有价格比较:前置事件处理还接收账户变动和配置变化。
已确认的处理顺序
MatchingEngineManager 中以 handleEventsWith(new SaveOrderHandler(...)).then(new MatchingBusinessHandler(...)) 连接两个处理阶段。
RequestMatchEvent
→ SaveOrderHandler
→ MatchingBusinessHandler
→ OrderBook 的对应操作
MatchingBusinessHandler.onEvent 首先判断引擎的 isRunning,然后检查 event.isSaveFile()。只有通过这个前置标记的事件才进入撮合分支。这个标记不能直接等同于整笔业务已完成或数据库事务已提交。
| 请求类型 | 已核对的处理 |
|---|---|
| ADD_ORDER | 从 MatchingEntrustDTO 取订单 ID、方向、价格、数量和交易对,调用 orderbook.enter |
| CANCEL_ORDER | 调用 orderbook.cancel(id, 0) |
| INIT_MATCH | 调用 orderbook.enterInit,使用 leftCount 和初始化完成标记 |
为什么分阶段
前一阶段处理请求及其前置状态,后一阶段才执行订单簿操作。阅读失败路径时,必须观察前置标记和运行状态,不能仅看请求是否进入队列。
异常路径
处理器记录异常,对 MatchingSaveFileException 继续抛出;其他异常在该处理器中被捕获。finally 调用 ResizeSemaphore.release()。因此,日志中出现异常后,还需检查事件结果、引擎状态和上层异常策略,不能假设系统自动重试。
源码阅读路线
service/MatchingEngineManager.java:事件处理顺序、publish、引擎管理。disruptor/SaveOrderHandler.java:前置处理与事件结果。disruptor/MatchingBusinessHandler.java:订单簿调用。book/OrderBook.java与book/RBTreeOrderBook.java:订单簿接口与实现。processor/MatchingEngineProcessor.java:沿成交回调继续追踪。
验证场景
在隔离环境中覆盖可立即成交、无法成交、部分成交后撤单、重复撤单和初始化剩余数量。分别记录请求结果、订单簿余量、委托状态及账户变化。价格优先和同价排序的完整规则,需要进一步结合订单簿代码与用例验证。
系统输入流程
provider/MatchEngineExecuteService.addOrder 检查相关状态与交易配置,构造 ADD_ORDER 类型的 RequestMatchEvent,再交给引擎响应处理。撤单入口使用缓存订单判断状态,构造 CANCEL_ORDER 事件。这里的入口与旧委托工程的桥接要分开核对:旧桥接 RPC 已注释,不能自动连接成一条成功链路。
成交与行情输出流程
ADD_ORDER / CANCEL_ORDER
→ 前置处理 → 订单簿变动 / 价格档位处理
→ PriceLevel 等位置生成深度与成交数据
→ MessageSenderHelper 缓存消息
→ 对应缓存发送方法尝试投递 MQ
→ 行情或其他结果消费者
MessageSenderHelper.sendDepthMsg 与 sendTradeMsg 当前实现首先写入内存队列;不能把调用成功直接记作 MQ 已送达。NEW_DEPTH_MSG、NEW_TRADE_MSG 的发送代码可与行情消费者对照,实际运行调度和投递结果仍需验证。
子工程分工
- matching-api:业务接口与模型。
- matching-provider:引擎、账户及缓存等实现。
- matching-es:检索相关实体工程。
- matching-admin:管理接入;OrderController 中历史普通下单、撤单方法也被注释,不能视为现成交易入口。
完整恢复与管理说明见撮合管理与恢复,接口连通证据见链路断点。
主流程中的细化说明
现货主流程已展开同步 Future 的完成时点、同价队列、当前 getDealPrice 三价规则、分档成交算例、账户缓存处理、MoveService 异步落地及消息缓存边界。前置成功、成交、数据库可见与行情送达分别核对。