日志系统设计原则:打好高频交易的可观测性地基

做高频交易系统,我最怕什么?不是行情波动,不是策略回撤,而是系统崩了之后,我连它怎么死的都不知道。

你想想看,一秒钟几万笔订单,微秒级的延迟抖动。如果日志系统没设计好,排查问题就像大海捞针。今天我就把我在实战中总结的日志设计三板斧分享给你——分级、标准化、轮转。

一、日志分级:给每条消息贴上「紧急程度」标签

日志分级,说白了就是给不同重要性的信息分个三六九等。我见过不少团队,所有日志全用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的日志。如果不做轮转,磁盘很快就会被写满。系统一旦写不了日志,就会直接挂掉——这可不是开玩笑。

我推荐这套轮转策略:

  1. 按大小轮转:每个日志文件最大500MB。超过就自动切分。
  2. 按时间轮转:每天生成一个新日志文件。文件名带上日期,比如 trading-2025-01-15.log
  3. 保留策略:保留最近30天的日志。超过30天的自动删除。
  4. 压缩归档:超过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 分区,专门放日志。

四、知识体系总览:一张图看懂日志系统设计

下面这张图,是我自己总结的日志系统设计核心逻辑。你可以把它当作一个检查清单,每次设计新系统时对照着看一遍。

高频交易日志系统设计核心逻辑 日志分级 日志格式标准化 日志轮转策略 级别定义 • DEBUG - 调试信息 • INFO - 常规信息 • WARN - 警告 • ERROR - 错误 • FATAL - 致命错误 生产环境:INFO及以上 字段规范 • 时间戳(毫秒级) • 线程ID • 交易ID(雪花算法) • 日志级别 • 类名/模块名 格式:[时间] [级别] [线程] [模块] [交易ID] 消息 轮转策略 • 按大小:500MB/文件 • 按时间:每天切分 • 保留:30天 • 压缩:7天后gz • 独立磁盘分区 避免日志撑爆系统盘 目标:可观测性 + 可排查性 + 可靠性

嗯,到这里,日志系统设计的三个核心原则就讲完了。分级让你知道该关注什么,标准化让你能快速定位问题,轮转策略保证系统不会因为日志而崩溃。这三者缺一不可。

我记得刚入行时,总觉得日志是小事,随便写写就行。直到有一次线上事故,因为日志格式不统一,排查花了整整8个小时。从那以后,我再也不敢轻视日志设计了。

你想想看,一个每秒处理上万笔订单的系统,如果日志系统没设计好,出了问题你连从哪查起都不知道。那才是真正的灾难。


公众号:蓝海资料掘金营,微信deep3321