二、系统总体架构:分层架构设计
做市商高频风控系统,说白了就是要在纳秒级别内做出决策。我见过太多团队一上来就堆技术栈,结果系统延迟高得离谱,风控反而成了拖后腿的环节。今天我就聊聊我个人习惯的分层架构设计思路。
先看一张整体架构图,后面我们一层层拆开讲。
2.1 数据层:一切的基础
数据层是整个系统的地基。地基不稳,上面再花哨也没用。我早期参与过一个项目,数据层用了通用的消息队列,结果行情峰值时队列积压,风控信号晚了整整一个tick——那笔损失够买好几台服务器了。
数据层要解决三个核心问题:
- 低延迟接入:交易所通常走UDP组播或私有二进制协议。我个人建议直接用DPDK收包,绕过内核协议栈。别用TCP,那东西在高频场景下就是灾难。
- 数据对齐:多源行情的时间戳必须统一。我习惯用硬件时间戳,精度能到纳秒级。软件时间戳?嗯,误差太大,容易误判。
- 历史回放:回测和复盘需要完整的数据快照。记得用内存映射文件,别一行行读磁盘。
2.2 计算层:真正的硬仗
计算层是风控系统的核心。说白了,就是把原始行情变成可决策的指标。这里我踩过不少坑。
计算层主要做这几件事:
- 实时指标计算:比如波动率、买卖价差、订单簿深度。这些计算必须用C++,别想着用Python。Python的GIL在高频场景下就是枷锁。
- 风险敞口监控:净头寸、最大亏损、杠杆率。这些指标要实时更新,我习惯用增量计算,别每次都全量重算。
- 压力测试:模拟极端行情下的风险暴露。这个可以异步跑,别阻塞主流程。
计算层的延迟优化,我总结了几条铁律:
| 优化手段 | 说明 | 效果 |
|---|---|---|
| 无锁队列 | 用环形缓冲区替代互斥锁,避免线程切换 | 延迟降低 60-80% |
| 内存池 | 预分配内存,避免运行时malloc/free | 延迟降低 40-50% |
| CPU亲和性 | 绑定核心,避免缓存抖动 | 延迟稳定性提升 |
| SIMD指令 | 批量处理向量化数据 | 吞吐量提升 2-4x |
2.3 决策层:风控的大脑
决策层负责「判断」。数据算好了,指标出来了,到底要不要熔断?要不要撤单?这就是决策层的事。
决策层我习惯用事件驱动架构:
- 规则引擎:把风控规则写成可配置的表达式。比如「当净头寸超过阈值时触发熔断」。别硬编码,否则每次改规则都要重启系统。
- 状态机:每个策略都有自己的状态。正常、预警、熔断、恢复。状态切换要清晰,别出现死循环。
- 多策略协调:不同策略的风控信号可能冲突。比如A策略要撤单,B策略要加仓。决策层要有优先级仲裁机制。
这里有个细节:决策层不能「想太多」。你想想看,行情每微秒都在变,决策逻辑如果超过3微秒,那还不如不做风控。我见过有人把机器学习模型塞进决策层,结果推理延迟几十微秒——这在高频场景下就是自杀。
2.4 执行层:最后一公里
执行层是风控系统的「手」。决策层说「撤单」,执行层就得真的把单子撤掉。这里最怕什么?最怕执行失败。
执行层的关键设计:
- 订单路由:直接连接交易所的API,别经过中间件。每多一层转发,就多几微秒延迟。
- 撤单管理:撤单请求要带唯一标识,防止重复撤单。我遇到过撤单指令发了两遍,结果交易所返回「订单不存在」——尴尬。
- 仓位同步:本地仓位和交易所仓位要保持一致。用增量同步,别每次都全量拉取。
- 异常处理:网络闪断、交易所拒绝、超时重试。这些都要有预案。
执行层的代码,我建议用「防御性编程」。每个API调用都要检查返回值,每个超时都要有兜底逻辑。别觉得麻烦,线上出问题的时候,这些检查能救命。
2.5 模块化与微服务思想
说完分层,再聊聊模块化。很多人一听到微服务就兴奋,觉得要拆成几十个服务。但在高频场景下,微服务要慎用。
我的建议是:
- 核心链路用单体:数据层→计算层→决策层→执行层,这条路径上的模块尽量在同一个进程内。用进程内通信,别走网络。
- 辅助功能用微服务:比如日志收集、监控告警、历史回放。这些可以独立部署,不影响主链路延迟。
- 接口要清晰:模块之间用接口隔离,别直接依赖实现。这样即使以后要拆分,改动成本也低。
2.6 高可用与低延迟设计
高可用和低延迟,听起来矛盾,其实可以兼得。关键是要分场景处理。
高可用设计:
- 主备切换:核心模块做1主1备,备机实时同步状态。切换时间控制在1秒内。
- 熔断降级:如果某个模块超时,自动降级。比如计算层挂了,决策层用上一帧的数据做判断。
- 心跳检测:每个模块每秒上报心跳。连续3次心跳丢失,触发告警。
低延迟设计:
- 零拷贝:数据从网卡到应用层,全程零拷贝。用DPDK + 共享内存。
- 无锁编程:核心路径上不要有锁。用CAS操作和内存屏障替代。
- 预分配资源:连接池、内存池、线程池。运行时不要动态创建资源。
你可能会问:「高可用和低延迟冲突怎么办?」我的答案是:核心链路保延迟,辅助链路保可用。比如风控决策必须低延迟,但日志上报可以容忍几毫秒延迟。分而治之,别混为一谈。
好了,这一章就聊到这里。下一章我们深入计算层,聊聊具体的指标计算和优化技巧。