4. 哨兵架构设计:哨兵系统的分层架构

高频行情坏账率哨兵系统需要处理海量实时行情数据,并在毫秒级内完成计算与告警。为满足高吞吐、低延迟、可扩展的要求,系统采用经典的四层分层架构:采集层、计算层、告警层、存储层。每一层职责清晰,层间通过轻量级消息队列或API解耦,便于独立扩展与维护。

架构设计原则:每一层只关注自己的核心职责,不跨层调用数据库或外部服务。层间通信使用异步消息(Kafka / Pulsar),避免同步阻塞导致行情积压。

4.1 四层架构总览

下图展示了哨兵系统的完整分层结构,以及数据在各层之间的流转路径:

哨兵系统四层架构总览 哨兵系统四层架构总览 采集层 行情网关 · 协议解析 · 数据清洗 · 时间戳校准 计算层 滑动窗口聚合 · 坏账率实时计算 · 异常检测模型 告警层 阈值判定 · 告警分级 · 通知路由 · 抑制与恢复 存储层 时序数据库 · 原始行情归档 · 告警事件库 · 元数据管理 数据流:采集 → 计算 → 告警 → 存储(并行写入)

4.2 采集层:行情入口与第一道防线

采集层是哨兵系统的数据入口,负责从交易所、行情源或消息中间件接收原始高频行情数据。该层必须处理协议多样性、数据乱序、重复数据等现实问题。

组件 职责 关键技术
行情网关 对接不同交易所的行情协议(FIX/FAST/Binary) Netty / Reactor 模型
协议解析器 将二进制或文本协议转为统一内部格式 Protobuf / FlatBuffers
数据清洗 去重、时间戳校准、异常值过滤 布隆过滤器 / 滑动去重
流量控制 背压机制防止下游过载 Reactive Streams / 令牌桶
采集层关键指标:单节点吞吐量 ≥ 100万 msg/s,端到端延迟 ≤ 1ms(从行情到达网关到输出清洗后数据)。

4.3 计算层:坏账率实时计算引擎

计算层是哨兵系统的核心大脑,接收采集层输出的标准化行情流,执行坏账率相关的实时计算逻辑。该层采用事件驱动 + 微批处理混合模式,兼顾延迟与计算精度。

  • 滑动窗口聚合:按时间窗口(如1秒、5秒、1分钟)统计成交笔数、失败笔数、坏账金额。
  • 坏账率公式:坏账率 = (失败成交笔数 + 异常撤销笔数) / 总成交笔数 × 100%
  • 异常检测模型:基于统计阈值(3σ)或轻量级机器学习模型(Isolation Forest)识别突发异常。
  • 状态管理:使用 RocksDB 或 Redis 维护窗口状态,支持故障恢复。
// 坏账率计算核心伪代码(Flink DataStream API)
DataStream<MarketTrade> trades = env.addSource(kafkaSource);

trades
  .keyBy(trade -> trade.getSymbol())
  .window(SlidingProcessingTimeWindows.of(Time.seconds(5), Time.seconds(1)))
  .aggregate(new BadRateAggregate())
  .filter(rate -> rate.getValue() > BAD_RATE_THRESHOLD)
  .map(rate -> new AlertEvent(rate.getSymbol(), rate.getValue(), System.currentTimeMillis()))
  .addSink(alertSink);
注意:计算层必须处理数据倾斜问题。热门股票(如AAPL、TSLA)的行情量可能是冷门股票的1000倍以上,需要采用二级Key拆分或动态负载均衡策略。

4.4 告警层:分级通知与智能抑制

告警层接收计算层输出的异常事件,根据预设规则进行分级、聚合、抑制,并路由到不同的通知渠道。避免告警风暴是告警层设计的首要目标。

告警层处理流程 告警层处理流程 异常事件输入 告警分级判定 P0 紧急告警 P1 重要告警 P2 一般告警 电话 + 短信 + 钉钉 短信 + 钉钉 + 邮件 钉钉 + 邮件(日汇总)

告警层核心功能包括:

  • 告警分级:P0(坏账率 > 5% 且持续10秒)→ 立即电话通知;P1(坏账率 > 3%)→ 短信+即时消息;P2(坏账率 > 1%)→ 邮件日报。
  • 告警抑制:同一标的在5分钟内不重复发送同级别告警,避免轰炸。
  • 告警恢复:当坏账率回落至阈值以下并持续30秒,自动发送恢复通知。

4.5 存储层:多模态数据持久化

存储层负责保存原始行情、计算结果、告警事件和元数据,为事后分析、模型训练和审计提供数据基础。不同数据类型使用不同的存储引擎,以优化读写性能。

数据类型 存储引擎 保留周期 主要查询模式
原始行情Tick InfluxDB / TimescaleDB 7天(热)→ 30天(温)→ 1年(冷) 按时间范围 + 标的查询
坏账率指标 Prometheus + Thanos 90天 实时仪表盘、趋势分析
告警事件 Elasticsearch 180天 全文检索、聚合统计
元数据/配置 MySQL / PostgreSQL 永久 CRUD、关联查询
存储层优化建议:原始行情数据写入量极大(每天TB级),建议使用列式存储 + 时间分区 + 数据降采样策略。热数据保留在SSD上,冷数据自动迁移到对象存储(S3/MinIO)。

4.6 层间通信与数据一致性

四层架构通过Apache Kafka作为核心消息总线解耦。每层只与Kafka交互,不直接调用其他层的API。这种设计带来以下优势:

  • 流量削峰:行情突发时,Kafka作为缓冲区吸收瞬时流量。
  • 故障隔离:某一层宕机不影响其他层正常运行。
  • 水平扩展:每层可独立增加消费者或生产者实例。
# 层间Topic命名规范
采集层输出: raw.market.tick.{exchange}.{symbol}
计算层输出: computed.badrate.{symbol}.{window}
告警层输出: alert.event.{level}
存储层消费: storage.raw.tick, storage.badrate, storage.alert
数据一致性保障:由于采用异步消息,计算层可能收到乱序数据。必须为每条行情数据携带单调递增的序列号,计算层在窗口聚合前先做序列号校验,丢弃或重排乱序数据,确保坏账率计算的准确性。