第三章:系统架构总览:微服务架构拆分、核心模块与通信方式

好,我们直接进入正题。这一章,我想跟你聊聊整个交易引擎的骨架长什么样。

很多人一上来就撸代码,结果做着做着发现模块之间像一团乱麻。我早期带团队时就吃过这个亏——一个撮合逻辑改了,清算那边跟着崩,风控也报警。说白了,就是架构没想清楚。

所以这一章,我们先画好蓝图。你想想看,一栋大楼的地基没打好,后面装修再漂亮也没用。

3.1 为什么必须拆成微服务?

交易系统不是普通的Web应用。它有几个硬伤:

  • 高并发:一秒几万笔订单进来,单机扛不住
  • 低延迟:撮合必须在毫秒级完成
  • 高可用:宕机一分钟,损失可能就是几百万
  • 业务复杂:撮合、清算、风控,每个环节都不同

如果全写在一个进程里,你想想看:

  • 风控卡住了,撮合也得等着
  • 清算出Bug,整个系统都得重启
  • 想扩容?只能整体扩,浪费资源

所以,微服务拆分是必然选择。我个人习惯按业务边界切分,每个服务独立部署、独立扩容、独立演进。

核心原则:高内聚、低耦合。每个模块只做一件事,并且做到极致。

3.2 核心模块拆解

一个典型的分布式交易引擎,我一般拆成四个核心模块:

3.2.1 接入层(Gateway)

这是系统的门面。所有外部请求都先打到这。

它负责:

  • 协议转换:把HTTP、WebSocket、TCP等不同协议转成内部统一的RPC调用
  • 鉴权与限流:谁在调用?是不是合法用户?每秒能调多少次?
  • 请求路由:把订单请求转发到对应的撮合引擎实例
  • 连接管理:维护长连接,推送行情和成交回报

我在项目中遇到过一个问题:接入层如果处理太慢,会直接拖垮整个系统。后来我们用了Netty做IO框架,配合无锁队列,才把单机吞吐提到10万+。

避坑指南:我曾经把鉴权逻辑写在接入层里,结果每次请求都查一次数据库,延迟直接飙到50ms。后来改成本地缓存+定期刷新,延迟降到1ms以内。

3.2.2 撮合引擎(Matching Engine)

这是整个系统的核心。说白了,就是「谁想买、谁想卖,帮他们配对」。

它需要:

  • 维护订单簿:买盘和卖盘,按价格时间排序
  • 执行撮合逻辑:价格优先、时间优先
  • 生成成交记录:谁买了多少、谁卖了多少、成交价是多少

嗯,这里要注意:撮合引擎是有状态的。订单簿不能丢,一旦宕机恢复,必须能从快照+日志重建。

我建议把撮合引擎设计成单线程模型。为什么?因为撮合本质上是顺序操作,多线程反而会引入锁竞争,降低性能。我在一个项目中试过多线程撮合,结果延迟反而比单线程高了3倍。

警告:千万不要在撮合引擎里做IO操作!比如查数据库、发网络请求。这些操作会阻塞线程,导致撮合延迟飙升。所有IO操作都应该异步化。

3.2.3 清算引擎(Clearing Engine)

撮合完了,钱和资产怎么划转?这就是清算引擎的事。

它负责:

  • 资金结算:买方扣钱、卖方加钱
  • 资产划转:买方加资产、卖方扣资产
  • 手续费计算:按规则扣手续费
  • 对账:确保账目一致

清算引擎是最终一致性的典型场景。撮合引擎可以很快,但清算必须保证数据绝对正确。我习惯用事件驱动的方式:撮合引擎生成成交事件,清算引擎消费事件,异步处理。

你想想看,如果清算和撮合同步执行,一笔成交要等清算完才能返回,那延迟得多高?

3.2.4 风控引擎(Risk Engine)

风控是交易系统的「刹车」。没有它,系统可能被恶意用户搞崩。

它负责:

  • 事前风控:下单前检查用户余额、持仓、限价等
  • 事中风控:监控异常交易行为,比如频繁撤单、自成交
  • 事后风控:分析历史数据,发现潜在风险

我在项目中遇到过一个大坑:风控引擎如果处理太慢,会拖慢整个下单流程。后来我们把风控规则做成可配置的,并且用规则引擎(比如Drools)来执行,才把单次风控检查时间控制在1ms以内。

关键点:风控引擎必须独立部署,不能和撮合引擎混在一起。否则风控出问题,撮合也跟着挂。

3.3 模块间通信方式

模块拆开了,怎么通信?这是架构设计的关键。

我一般用三种方式:

通信方式 适用场景 优点 缺点
同步RPC(gRPC/Thrift) 接入层→撮合引擎 低延迟、强一致性 耦合度高
异步消息(Kafka/RocketMQ) 撮合引擎→清算引擎 解耦、削峰填谷 最终一致性
事件总线(Redis Pub/Sub) 行情推送、状态通知 实时性高 可靠性一般

具体来说:

  • 接入层到撮合引擎:我用gRPC。为什么?因为下单请求需要实时响应,gRPC基于HTTP/2,延迟低、性能好。
  • 撮合引擎到清算引擎:我用Kafka。撮合引擎只管生成成交事件,清算引擎异步消费。这样即使清算引擎挂了,消息也不会丢。
  • 风控引擎:我把它设计成「旁路」模式。下单时,接入层先调风控接口检查,通过后再转发给撮合引擎。这样风控不会成为瓶颈。

个人经验:我曾经用RabbitMQ做撮合和清算之间的通信,结果有一次消息堆积,清算延迟了10分钟。后来换成Kafka,配合分区机制,再也没出过问题。Kafka的持久化和重试机制,在金融场景下真的很稳。

3.4 整体架构图

说了这么多,不如一张图来得直观。下面是我画的一个简化版架构图:

分布式交易引擎核心架构 接入层 (Gateway) 协议转换 / 鉴权 / 限流 连接管理 / 请求路由 风控引擎 (Risk) 事前检查 / 事中监控 事后分析 / 规则引擎 同步RPC 撮合引擎 (Matching) 订单簿维护 / 撮合逻辑 成交生成 / 状态管理 gRPC 清算引擎 (Clearing) 资金结算 / 资产划转 手续费计算 / 对账 Kafka 消息队列 成交事件 / 清算指令 异步消息 异步消费 数据库集群 订单 / 成交 / 账户 图例 核心服务 同步调用 异步消息 数据库访问

这张图展示了核心模块之间的通信关系。你可以看到:

  • 接入层通过gRPC调用撮合引擎,同时旁路调用风控引擎
  • 撮合引擎通过Kafka异步通知清算引擎
  • 所有模块都访问数据库,但访问方式不同

3.5 架构设计的一些思考

最后,我想分享几个我在实际项目中踩过的坑:

  1. 不要过度拆分。我见过有人把撮合引擎拆成「订单接收服务」和「撮合执行服务」,结果两个服务之间通信延迟比撮合本身还高。微服务的粒度要适中。
  2. 通信方式要统一。团队里有人用gRPC,有人用HTTP,有人用消息队列,最后维护成本极高。我建议一个系统内最多用两种通信方式:同步用gRPC,异步用Kafka。
  3. 监控和链路追踪必须跟上。微服务拆了之后,一个请求可能经过5-6个服务。没有链路追踪,出了问题你根本不知道在哪。我习惯用Jaeger做全链路追踪。

重要提醒:架构设计没有银弹。你看到的每个方案,都是权衡的结果。比如同步RPC延迟低但耦合高,异步消息解耦好但延迟高。选哪个?取决于你的业务场景。

好了,这一章我们画好了蓝图。下一章,我会带你深入撮合引擎的核心——订单簿的设计与实现。那是整个系统最硬核的部分,准备好了吗?


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