一文讲透:加密货币交易所现货系统全链路(从下单到成交再到资金结算)

3 阅读5分钟

一文讲透:加密货币交易所现货系统全链路(从下单到成交再到资金结算)

             用户 / API
                  ↓
              API网关
                  ↓
   ┌────────交易主线────────┐
   ↓                       ↓
订单系统 →  撮合引擎 →  行情系统
   ↓
资金结算 → 账户系统 → 钱包

   ┌────────风控主线────────┐
   ↓                       ↓
实时风控 →  规则引擎 →  风控数据

   ┌────────数据底盘────────┐
   ↓                       ↓
Kafka → Flink → ClickHouse/Redis/S3

在很多人的认知里,交易所的核心就是“撮合引擎”。
但真正进入生产环境后你会发现:

交易所本质不是撮合系统,而是一个围绕“订单 + 资金 + 状态”构建的分布式闭环系统。

这篇文章,我会带你从工程视角,把现货交易所的完整链路拆开讲清楚,并且告诉你每一块真正的复杂点在哪里。


一、整体认知:交易所到底在干什么?

先用一句话定性:

交易所的核心任务,是在高并发下,保证订单撮合正确、资金绝对准确、系统最终一致。

整个系统可以拆成六大核心链路:

  1. 下单链路(入口)
  2. 撮合链路(核心)
  3. 成交与清算链路(资金流转)
  4. 撤单链路(状态收敛)
  5. 账户账务系统(资金底座)
  6. 补偿与对账链路(最终兜底)

image.png


二、下单链路:不是写订单这么简单

用户点击“买入”的那一刻,系统其实已经做了很多事情:

核心步骤

  • 鉴权(API Key / 用户状态)
  • 幂等校验(防重复下单)
  • 交易规则校验(精度、最小下单量)
  • 风控前置拦截(IP / 设备 / 行为)
  • 资产冻结(最关键一步)
  • 订单落库
  • 投递撮合队列

image.png

为什么这里容易出问题?

很多系统问题,其实出在这里:

  • 冻结成功但订单创建失败 → 资金被锁死
  • 幂等没做好 → 重复扣钱
  • 风控放过异常订单 → 后面再拦已经晚了

本质问题:
“用户意图”到“系统状态”这一步,必须是原子且可回滚的。


三、撮合链路:快,但还要可恢复

撮合引擎负责一件事:

找到买卖双方,让他们成交。

核心机制

  • 价格优先
  • 时间优先
  • 内存订单簿(OrderBook)
  • 逐笔撮合(match loop)

image.png

真正的难点不在“撮合”,而在:

1)状态恢复(Snapshot + Replay)

撮合引擎通常是内存态,一旦重启:

  • 如何恢复盘口?
  • 如何保证顺序一致?
  • 如何避免重复成交?

解决方案通常是:

  • 定期快照(snapshot)
  • 日志回放(replay)

2)顺序一致性

撮合是强顺序系统:

  • 同一交易对必须串行
  • 否则价格会错乱

3)性能与延迟

  • 毫秒级甚至微秒级延迟要求
  • 高并发订单处理

总结一句话:

撮合引擎难在“快 + 顺序 + 可恢复”。


四、成交与清算:钱真正开始动的地方

撮合只告诉你:

  • 谁和谁成交了
  • 价格多少
  • 数量多少

钱还没动

image.png

清算要做什么?

  • 买方:扣钱 + 加币
  • 卖方:扣币 + 加钱
  • 手续费计算(maker / taker / VIP)
  • 账务入账
  • 更新订单成交信息

最大风险点

❗ 幂等问题

成交消息可能:

  • 重复消费
  • 重试
  • 网络抖动

如果没做幂等:

会发生“双倍入账”或“双倍扣款”


❗ 资金守恒

必须保证:

用户资产 = 可用 + 冻结 + 成交变化

一旦不守恒,就是事故。


总结一句话:

撮合决定“成交”,清算决定“钱对不对”。


五、撤单链路:最容易被低估的复杂点

image.png

很多人觉得撤单很简单:

“从盘口删除订单就完了”

但真实情况是:

撤单 vs 成交是并发竞争关系

可能出现:

  • 用户发起撤单
  • 同时订单被撮合成交

结果可能是:

  • 已成交
  • 部分成交 + 撤单
  • 已撤单

正确做法

必须由撮合引擎裁决最终结果

而不是 API 自己判断:

  • 是否在盘口 ❌
  • 是否可撤 ❌

总结一句话:

撤单的本质,是“订单终态收敛问题”。


六、账户账务系统:交易所真正的命门

这是很多人低估的模块。

image.png

它负责什么?

  • 可用余额
  • 冻结余额
  • 成交入账
  • 手续费扣除
  • 多币种管理

为什么它最难?

因为:

任何情况下都不能算错钱。

典型问题:

  • 下单冻结成功,但订单失败
  • 成交和撤单同时发生
  • MQ 重复消费
  • 跨系统资金不一致

总结一句话:

撮合挂了是“不能交易”,账务挂了是“交易所倒闭”。


七、补偿与对账:系统的最后防线

image.png

再完美的系统,也会出现:

  • 消息丢失
  • 状态错乱
  • 网络异常

所以必须有:

核心能力

  • 定时扫描异常订单
  • 对账(订单 / 成交 / 账务)
  • 自动修复状态
  • 人工介入通道

典型补偿场景:

  • 订单一直卡在 TRADING
  • 成交已发生,但订单未更新
  • 冻结未释放

总结一句话:

补偿系统决定了系统“最终是否正确”。


八、为什么说交易所是“状态机系统”?

image.png

把整个流程抽象一下:

  • 下单 → 状态变化
  • 撮合 → 状态变化
  • 成交 → 状态变化
  • 撤单 → 状态变化

最终所有订单必须收敛到:

  • 已成交(FILLED)
  • 已撤单(CANCELED)

本质:

交易所 = 状态机 + 消息队列驱动系统


九、复杂度最高的系统是谁?

很多人以为是撮合,其实不完全对。

实际复杂度排序

第一梯队:

  • 合约风险引擎
  • 账户账务系统
  • 撮合引擎

第二梯队:

  • 清算结算系统
  • 钱包充提系统
  • 风控引擎

原因很简单:

  • 撮合难在“快”
  • 账务难在“不能错”
  • 风控难在“识别对不对”

十、总结

如果用一句话总结整个交易所系统:

交易所不是撮合系统,而是一个围绕订单、撮合、账务构建的分布式状态机系统,通过消息驱动实现解耦,通过补偿机制保证最终一致性,通过风控体系筛选风险行为。


写在最后

真正重要的不是:

  • 某一个接口怎么写
  • 某一个模块怎么实现

而是:

  • 系统是否可收敛
  • 状态是否一致
  • 资金是否绝对正确

这,才是交易所系统的本质。


主要参考来自于:浅谈撮合引擎实现原理