日志系统设计原则:打好高频交易的可观测性地基
做高频交易系统,我最怕什么?不是行情波动,不是策略回撤,而是系统崩了之后,我连它怎么死的都不知道。
你想想看,一秒钟几万笔订单,微秒级的延迟抖动。如果日志系统没设计好,排查问题就像大海捞针。今天我就把我在实战中总结的日志设计三板斧分享给你——分级、标准化、轮转。
一、日志分级:给每条消息贴上「紧急程度」标签
日志分级,说白了就是给不同重要性的信息分个三六九等。我见过不少团队,所有日志全用INFO,结果线上出故障时,关键信息淹没在「连接成功」「心跳正常」这类废话里。
标准分级体系(我推荐这套):
| 级别 | 含义 | 典型场景 | 我是否打印到控制台 |
|---|---|---|---|
| DEBUG | 调试信息 | 变量值、函数入参、中间计算结果 | ❌ 仅开发环境 |
| INFO | 常规信息 | 系统启动、订单接收、成交回报 | ✅ 生产环境也保留 |
| WARN | 警告 | 网络重试、延迟超标、风控阈值接近 | ✅ 黄色高亮 |
| ERROR | 错误 | 订单拒单、数据库连接失败、行情断连 | ✅ 红色高亮,立即告警 |
| FATAL | 致命错误 | 内存溢出、核心线程崩溃、数据损坏 | ✅ 红色闪烁,触发系统重启 |
我的个人习惯:生产环境只开INFO及以上级别。DEBUG日志只在压测或复现bug时临时开启。千万别在生产环境开DEBUG——我见过有人这么干,结果一天写了200GB日志,磁盘直接打满。
二、日志格式标准化:让机器和人都能一眼看懂
日志格式不统一,是排查问题的头号杀手。我曾经接手过一个老系统,有的日志用「|」分隔,有的用「,」,有的干脆是自由文本。每次查问题都得写一堆正则表达式去解析,痛苦不堪。
我建议的标准化格式长这样:
[2025-01-15 14:23:45.123] [INFO] [Thread-12] [OrderService] [TxnID: TX20250115-00012345] 收到订单请求: symbol=BTCUSDT, side=BUY, price=50000.00, qty=0.1
拆开来看,每个字段都有讲究:
- 时间戳:精确到毫秒,格式统一用
yyyy-MM-dd HH:mm:ss.SSS。高频交易里,微秒级差异可能就是盈亏的分水岭。 - 线程ID:方便追踪并发问题。我习惯用
[Thread-{id}]格式,一眼就能看出是哪个线程在干活。 - 交易ID:这是高频交易日志的灵魂。每个订单、每个成交、每个撤单请求,都必须带上唯一的交易ID。这样你才能把一条请求从「收到」到「成交」的完整链路串起来。
我曾经踩过的坑:交易ID生成器用了 UUID.randomUUID(),结果在高并发下出现了重复ID。排查了整整两天才发现是时钟回拨导致的。后来我改用雪花算法(Snowflake),配合独立的ID生成服务,再也没出过问题。
三、日志轮转策略:别让日志撑爆你的磁盘
高频交易系统一天能产生几十GB的日志。如果不做轮转,磁盘很快就会被写满。系统一旦写不了日志,就会直接挂掉——这可不是开玩笑。
我推荐这套轮转策略:
- 按大小轮转:每个日志文件最大500MB。超过就自动切分。
- 按时间轮转:每天生成一个新日志文件。文件名带上日期,比如
trading-2025-01-15.log。 - 保留策略:保留最近30天的日志。超过30天的自动删除。
- 压缩归档:超过7天的日志自动压缩成
.gz格式。压缩率能达到10:1,省空间。
具体实现上,我一般用 Logback 或 Log4j2 的 SizeAndTimeBasedRollingPolicy。配置大概长这样:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/trading.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/trading-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%logger{36}] [%X{txnId}] %-5level - %msg%n</pattern>
</encoder>
</appender>
一个小技巧:把日志文件放在单独的磁盘分区上。这样即使日志写满,也不会影响系统盘。我习惯挂载一个 /data/logs 分区,专门放日志。
四、知识体系总览:一张图看懂日志系统设计
下面这张图,是我自己总结的日志系统设计核心逻辑。你可以把它当作一个检查清单,每次设计新系统时对照着看一遍。
嗯,到这里,日志系统设计的三个核心原则就讲完了。分级让你知道该关注什么,标准化让你能快速定位问题,轮转策略保证系统不会因为日志而崩溃。这三者缺一不可。
我记得刚入行时,总觉得日志是小事,随便写写就行。直到有一次线上事故,因为日志格式不统一,排查花了整整8个小时。从那以后,我再也不敢轻视日志设计了。
你想想看,一个每秒处理上万笔订单的系统,如果日志系统没设计好,出了问题你连从哪查起都不知道。那才是真正的灾难。
公众号:蓝海资料掘金营,微信deep3321