4. 架构分层设计:接入层、逻辑层、数据层的分层策略、各层的高可用目标
做市商系统,说白了就是一台高速运转的印钞机——前提是它不能停。
我见过太多团队,一上来就追求极致的低延迟,结果系统三天两头出故障。你想想看,一个每秒处理几万笔订单的系统,如果因为架构耦合太紧导致雪崩,那损失可不是闹着玩的。
所以,分层设计是我做架构时第一个要敲定的事。今天咱们就聊聊接入层、逻辑层、数据层这三层怎么拆,每层的高可用目标又是什么。
4.1 为什么必须分层?
不分层的架构,就像把所有的鸡蛋放在一个篮子里。一旦某个环节出问题,整个系统就瘫了。
我个人习惯把做市商系统拆成三层:
- 接入层:负责跟外部打交道,比如交易所、行情源、客户端。
- 逻辑层:核心业务逻辑,比如定价、风控、订单管理。
- 数据层:负责数据持久化,比如订单簿、账户余额、历史记录。
每一层各司其职,互不干扰。这样出了问题,我们能快速定位,也能单独做高可用。
4.2 接入层:守好大门
接入层是系统的脸面。所有外部请求都从这里进来。
它的高可用目标很明确:连接不断、请求不丢、流量可控。
4.2.1 连接管理
做市商系统通常需要跟多个交易所保持长连接。我记得有一次,某个交易所的API突然升级,导致我们的连接全部断开。那叫一个惨,订单直接卡死。
从那以后,我要求接入层必须做到:
- 多活连接:每个交易所至少建立2条独立连接,一条主用,一条备用。
- 心跳检测:每100ms发一次心跳,连续3次没响应就自动切换。
- 连接池化:复用连接,避免频繁创建销毁带来的开销。
4.2.2 流量整形
行情数据有时候会突然暴增,比如重大新闻发布时。如果接入层不做限流,逻辑层瞬间就会被冲垮。
我常用的策略是:
- 令牌桶限流:控制每秒进入逻辑层的请求数。
- 请求去重:同样的订单请求,只处理一次。
- 熔断降级:如果逻辑层响应超时,接入层直接返回失败,避免堆积。
4.3 逻辑层:核心大脑
逻辑层是系统最复杂的一层。定价、风控、订单路由都在这里完成。
它的高可用目标:计算准确、状态一致、故障自愈。
4.3.1 无状态设计
逻辑层最好设计成无状态的。什么意思?就是每个节点不保存任何本地状态,所有状态都丢到数据层去。
这样做的好处是:
- 水平扩展:加机器就能提升处理能力。
- 故障转移:一个节点挂了,另一个节点直接接管,没有状态丢失。
你想想看,如果逻辑层节点保存了订单的中间状态,一旦宕机,那些订单就丢了。这在做市商系统里是绝对不能接受的。
4.3.2 幂等性保障
网络抖动是常态。同一个订单请求可能被重复发送。
逻辑层必须保证幂等性:同样的请求,处理一次和处理多次,结果一样。
我通常的做法是:
- 每个请求带一个全局唯一的ID。
- 逻辑层处理前先查一下这个ID是否已经处理过。
- 如果处理过,直接返回上次的结果。
4.4 数据层:持久化基石
数据层是系统的最后一道防线。所有订单、账户、行情数据最终都要落盘。
它的高可用目标:数据不丢、读写分离、快速恢复。
4.4.1 主从复制与分片
单库单表肯定扛不住做市商系统的写入量。我一般用分片+主从复制:
- 分片:按交易对或者用户ID把数据分散到多个数据库。
- 主从复制:每个分片至少一主一从,主库负责写,从库负责读。
这样即使某个分片的主库挂了,从库能秒级切换成主库,业务几乎不受影响。
4.4.2 数据一致性
做市商系统对数据一致性要求极高。尤其是账户余额,绝对不能出现对不上账的情况。
我常用的方案是:
- 两阶段提交:对于关键操作,比如扣款和下单,必须保证原子性。
- 对账机制:每隔一段时间,用离线任务把数据库里的订单和交易所的成交记录做一次比对。
4.5 分层架构的核心逻辑图
下面这张图,是我做分层设计时经常用的参考。它清晰地展示了三层之间的协作关系:
4.6 各层之间的协作要点
分层不是把系统拆开就完事了。层与层之间的协作,才是高可用的关键。
- 超时控制:接入层调用逻辑层时,必须设置超时时间。我一般设500ms,超过就熔断。
- 异步解耦:逻辑层写入数据层时,尽量用异步方式。比如订单落库,先写到消息队列,再由消费者慢慢处理。
- 降级策略:如果数据层挂了,逻辑层能不能降级?比如暂时不更新订单簿,只做报价。这个需要提前设计好。
好了,关于分层设计,今天就聊这么多。记住,分层不是为了炫技,而是为了在系统出问题时,我们能睡得着觉。