第三章:系统架构总览——分层架构设计、微服务 vs 单体、高可用原则

做市商系统,说白了就是一台高速运转的印钞机——前提是你得把它造对。

我见过太多团队,一上来就撸代码,结果三个月后发现自己掉进了泥潭。为什么?因为架构没想清楚。今天这一章,咱们就把做市商系统的骨架聊透。我会从分层架构、服务选型、高可用设计三个维度展开,中间穿插一些我踩过的坑。

一、分层架构设计:接入层、业务层、数据层

我个人习惯,做任何系统都先画三层。不是老套,是管用。

做市商系统尤其如此。你想想看,行情数据每秒进来几千笔,订单要毫秒级响应,风控还得实时拦截——不分层,代码就是一锅粥。

1. 接入层:系统的脸面

接入层负责跟外界打交道。包括交易所的行情推送、订单网关、WebSocket连接管理、REST API接口。

这里有个关键点:协议转换。交易所用FIX协议,内部系统用Protobuf,中间得有个适配层。我在项目中遇到过,某次交易所升级了FIX版本,结果我们的网关没跟上,直接断连了半小时。嗯,从那以后我强制要求接入层必须支持热加载协议配置。

接入层核心职责:
  • 连接管理(心跳、重连、限流)
  • 协议解析与序列化
  • 身份认证与权限校验
  • 流量整形(防止上游突发流量打垮下游)

2. 业务层:大脑所在

业务层是核心。定价引擎、订单管理、风险控制、仓位核算,全在这里。

我建议业务层一定要做无状态设计。为什么?因为只有无状态才能水平扩展。你想想看,如果每个业务实例都维护着本地订单状态,一旦宕机,那堆状态就丢了。我曾经接手过一个项目,业务层用本地HashMap存订单,每次重启都得等恢复脚本跑半小时——惨不忍睹。

业务层的典型模块:

  • 定价引擎:根据市场深度、库存、波动率计算报价
  • 订单路由:决定订单发往哪个交易所
  • 风控模块:检查单笔限额、日内亏损、持仓集中度
  • 清算对账:与交易所逐笔核对成交和资金

3. 数据层:一切的基础

数据层不只是存数据,更是数据的组织方式

做市商系统的数据有几个特点:

  • 高频写入(行情、订单、成交)
  • 低延迟查询(实时仓位、风险敞口)
  • 强一致性要求(资金、持仓不能错)

所以数据层不能只用一种数据库。我常用的组合是:

数据类型 存储方案 原因
行情快照 Redis / 内存数据库 纳秒级读写,不持久化也行
订单流水 Kafka + 时序数据库 高吞吐写入,按时间范围查询
资金持仓 关系型数据库(MySQL/PostgreSQL) 事务支持,强一致性
历史分析 列式存储(ClickHouse) 大范围聚合查询快
小技巧: 资金持仓表一定要用乐观锁或分布式锁,别问我怎么知道的——有一次线上两个线程同时更新同一笔资金,结果账对不上了,排查了一整夜。

二、微服务 vs 单体架构选型

这个问题,每次跟同行聊都能吵起来。我的态度很明确:看阶段,看规模

1. 单体架构:起步快,但别贪心

如果你团队只有三五个人,日交易量不到一万笔,单体架构完全够用。我第一个做市商项目就是单体,一个Java进程搞定所有。开发快、部署简单、调试方便。

但单体有个致命问题:故障隔离差。定价引擎挂了,整个系统都瘫。我记得有一次风控模块内存泄漏,结果订单网关也跟着挂了,交易所那边直接发了警告函。

什么时候该拆?
  • 团队超过10人,代码合并冲突频繁
  • 某个模块需要独立扩缩容(比如行情处理需要10个实例,但风控只需要2个)
  • 某个模块的故障会拖垮整个系统

2. 微服务:灵活,但别过度

微服务的好处不用我多说:独立部署、独立扩缩、技术栈灵活。但代价也很明显——分布式复杂性

我建议做市商系统拆成这几个微服务就够了:

  • 行情服务:接收、清洗、分发行情数据
  • 定价服务:计算买卖报价
  • 订单服务:管理订单生命周期
  • 风控服务:实时风险检查
  • 清算服务:对账、结算

别拆太细。我曾经见过一个团队把定价引擎拆成三个服务——计算买价、计算卖价、计算价差。结果一次行情波动,三个服务之间来回调用,延迟从50微秒飙到5毫秒。嗯,过度设计的代价。

我的选型建议:
  • 初创期:单体 + 模块化设计(为后续拆分留接口)
  • 成长期:按核心业务拆4-6个微服务
  • 成熟期:根据性能瓶颈和团队规模精细化拆分

三、高可用设计原则

做市商系统,宕机就是亏钱。我见过最惨的一次,某团队系统宕了15分钟,结果市场剧烈波动,重新上线后持仓已经亏了200万。所以高可用不是锦上添花,是生存底线。

1. 冗余设计:别把所有鸡蛋放一个篮子

每个关键组件都要有备用。交易所连接至少两条线路,数据库做主从复制,服务实例至少两个副本。

我习惯用N+1原则:正常需要N个实例,那就部署N+1个。多出来的那个平时分担流量,故障时自动接管。

2. 优雅降级:宁可少功能,不能全挂

系统压力过大时,要有策略地放弃非核心功能。比如:

  • 行情展示可以降级为只显示最新价,不显示深度图
  • 历史查询可以返回缓存数据,不查数据库
  • 风控可以暂时只检查最大限额,跳过复杂模型

我在项目中遇到过,某次行情数据量暴增10倍,数据库扛不住了。我们紧急降级了历史查询和报表生成,保住了核心交易链路。虽然用户看不到历史K线了,但至少还能交易。

3. 限流与熔断:保护系统不被冲垮

做市商系统最怕什么?突发流量。比如某个币种突然暴涨,所有用户同时下单,系统瞬间被打爆。

我建议在接入层做令牌桶限流,在业务层做熔断器。限流防止外部流量过大,熔断防止内部故障扩散。

// 伪代码:令牌桶限流
public class TokenBucket {
    private long capacity;    // 桶容量
    private long tokens;      // 当前令牌数
    private long lastRefill;  // 上次补充时间
    
    public boolean tryAcquire() {
        refill(); // 按速率补充令牌
        if (tokens > 0) {
            tokens--;
            return true;
        }
        return false; // 限流了
    }
}

4. 监控与告警:看不见的故障最可怕

高可用不只是架构设计,更是运维能力。我要求每个服务必须暴露以下指标:

  • QPS、延迟P99、错误率
  • 连接数、内存使用率、GC频率
  • 订单成功率、成交延迟

告警要分级。P0级(系统不可用)直接打电话,P1级(功能受损)发短信,P2级(性能下降)发邮件。我曾经因为告警阈值设得太低,半夜被电话吵醒三次,结果发现只是网络抖动——从那以后我学乖了,告警要设置持续时间和次数。

避坑指南: 监控系统本身也要高可用。我见过有人把监控部署在同一个集群里,结果集群挂了,监控也跟着挂了——你都不知道系统已经宕了。监控一定要独立部署。

架构总览图

下面这张图,是我做市商系统架构的核心逻辑。你可以看到三层之间如何协作,以及高可用组件如何穿插其中。

接入层 行情网关 订单网关 REST API 限流器 业务层 定价引擎 订单管理 风控模块 清算对账 数据层 Redis(缓存) Kafka(消息) MySQL(资金) ClickHouse 高可用贯穿全层

这张图里,三层之间通过消息队列和RPC通信。高可用不是某一层的任务,而是贯穿始终的设计思想。每一层都要有冗余、限流、降级和监控。


好了,这一章的内容就到这里。架构设计没有银弹,但分层、微服务、高可用这三个维度,能帮你搭建一个经得起市场考验的系统。下一章我们会深入定价引擎的设计,那是做市商系统的核心大脑。

本章核心要点:
  • 分层架构:接入层管连接,业务层管逻辑,数据层管存储
  • 微服务 vs 单体:看阶段选型,别为了微服务而微服务
  • 高可用三件套:冗余、降级、限流熔断
  • 监控告警要独立部署,别让自己变成瞎子

专注资料整理