本文最后更新于 2 分钟前,文中所描述的信息可能已发生改变。
项目描述
证券交易系统 (后端开发、测试) 2024.10 - 2025.02
应用技术:SpringBoot
SpringCloud
Kafka
Redis
MySQL
Docker
项目描述:本项目实现单一交易对的高性能证券交易系统,逻辑上划分为交易引擎、API、定序、行情、推送等模块,实现订单创建、订单取消、行情处理等功能,能够实现全天候交易,实时更新市场行情。
项目网址:https://github.com/helltractor/trading-exchange-system
项目亮点
- 全局消息定序: 通过全局唯一的 UniqueID、严格递增的 SequenceID 和前驱事件 PreviousID 组合,确保事件消息全链路的顺序一致性,有效防止消息重复处理和丢失。
- 交易引擎设计: 采用完全基于内存的交易引擎架构,大幅提升撮合速度和系统 TPS,同时通过异步持久化机制保障引擎崩溃后的数据恢复,确保数据可靠性。
- 撮合引擎优化: 采用双 TreeMap 结构构建订单簿(买盘倒序/卖盘正序),基于 SequenceID 时序和价格优先级进行双重排序,实现高效撮合和实时订单状态更新,确保系统稳定性。
- API 模块设计: 提供 RESTful API,满足下单、撤单、查询订单状态等核心交易功能需求。采用 DeferredResult 异步处理请求,实现低延迟的用户交互体验。
- 行情消息更新: 基于 Redis 原子化操作特性,通过 Lua 脚本实现行情数据的强一致性更新,利用 Redis Pub/Sub 通道进行实时广播,确保行情消息的及时性和准确性。
- 市场信息推送: 采用 Vert.x 框架构建高并发推送系统,高效管理海量 WebSocket 连接,订阅 Redis 消息实现市场数据的实时推送,满足高并发和低延迟的需求。
项目漏洞
1. 全局消息定序机制:
问题:依赖 SequenceID 和 PreviousID 的时序假设
如果网络抖动或消息丢失,PreviousID 可能无法及时对齐,导致消息阻塞或顺序错乱。
如果一个消息丢了但没有重发机制,可能造成后续消息全部失效。
建议:
引入 Paxos/Raft 等共识协议来保证多节点顺序一致性。
或者实现类似 Kafka 的 Partition + Offset 管理方式,并配合 ACK + 重试机制防丢失。
2. 基于内存的交易引擎:
问题:数据落盘是异步的,如果崩溃发生在持久化前,会存在数据丢失风险
建议:
引入 Write-Ahead Log(预写式日志 WAL)机制。
或使用高性能本地持久化技术(如 Chronicle Queue、Disruptor RingBuffer + mmap 文件落盘)。
3. 撮合引擎(TreeMap 双结构):
问题:TreeMap 本身是线程不安全的;高并发下可能存在数据竞争
建议:
引入
ConcurrentSkipListMap
或使用读写锁来保护撮合核心逻辑。或使用更高性能的撮合结构,如 Price-Level Queue(价格级队列),配合 price → list 结构。
4. Redis + Lua 脚本更新行情:
问题:Redis 单线程,Lua 执行过程中阻塞所有其他命令;高频行情下可能成为瓶颈
建议:
限制 Lua 脚本的逻辑复杂度和执行时间。
拆分行情粒度,按品种分散到多个 Redis 实例。
5. Vert.x WebSocket 推送系统:
问题:WebSocket 长连接需要心跳维持;如果客户端断开无检测机制,会占用资源
建议:
每隔 X 秒发 Ping/Pong 心跳。
检测 stale 连接并及时关闭。
量化指标与测试方式设计
模块 | 指标 | 测试方式 |
---|---|---|
全局消息定序 | - 顺序一致性 - 消息无丢失率(≦0.01%) | - 构造 1000 万条消息流,插入乱序包,验证是否顺序输出 - 故障注入(kill publisher),观察恢复后 ID 连续性 |
内存撮合引擎 | - 撮合 TPS ≥ 10W/s - 撮合延迟 P99 ≦ 2ms | - 用 JMH 构造 OrderMatchBenchmark,模拟百万用户下单 - profile GC 情况,检测内存访问与锁竞争 |
数据可靠性(异步持久化) | - 崩溃恢复数据一致性 > 99.999% | - 在交易高峰期强制 kill 掉 engine 进程,重新拉起后比对 snapshot + WAL 的重放结果 |
API 延迟 | - REST API 响应延迟 P99 ≦ 20ms - 异常请求错误率 ≦ 0.1% | - 使用 Gatling/Locust 进行 10 万并发压测,持续 10 分钟 - 模拟超时、错误参数等请求注入 |
行情更新与广播 | - Redis 更新延迟 ≦ 5ms - 广播延迟 P99 ≦ 10ms | - 统计每个 Lua 脚本的执行时间(INFO 命令 + latency monitor) - 模拟 1 万客户端,用 WebSocketClient 采样接收时间戳差 |
推送系统并发能力 | - 支持连接数 ≥ 10 万 - 心跳丢失率 ≦ 0.1% | - 使用 Netty/Vert.x 压测工具模拟 WebSocket 客户端并发连接 - 启动 TCP Dump 检测连接是否成功完成三次握手并保持活跃 |