3. 数据采集层架构:多源异构数据接入
数据采集层,说白了就是交易监控系统的「耳朵」和「眼睛」。
你想想看,一个监控系统要是连数据都拿不到,或者拿到的数据是错的、延迟的,那后面的分析、告警全是白搭。我个人习惯把这一层叫做「数据入口的守门员」——它决定了整个系统的数据质量天花板。
3.1 三大数据源:交易所API、FIX协议、消息队列
在实际项目中,我们面对的从来不是单一数据源。我做过一个监控系统,同时接了3家交易所的REST API、2条FIX链路、还有内部Kafka集群的行情流。嗯,这里面的坑,我一个个说。
3.1.1 交易所API接入
交易所API是最常见的数据来源。但每家交易所的接口风格、限流策略、数据格式都不一样。
- REST API:适合低频数据(如订单状态、账户余额)。我建议用连接池+重试机制,避免单点故障。
- WebSocket:适合高频行情(如逐笔成交、深度快照)。注意心跳保活和断线重连。
- 限流处理:我曾经遇到一家交易所,每秒只允许10次请求。超了直接封IP。后来我加了令牌桶算法,才稳住。
// 伪代码:交易所API接入适配器
public class ExchangeAdapter {
private RateLimiter limiter = RateLimiter.create(10); // 每秒10次
public MarketData fetchDepth(String symbol) {
limiter.acquire(); // 限流
try {
return httpClient.get("/depth", symbol);
} catch (RateLimitExceeded e) {
// 退避重试
Thread.sleep(1000);
return fetchDepth(symbol);
}
}
}
3.1.2 FIX协议接入
FIX协议在机构交易中几乎是标配。它是个二进制协议,解析起来比JSON麻烦得多。
我记得第一次接触FIX时,被它的Tag-Value格式搞晕了。比如 35=D 表示新订单,55=600519 表示股票代码。每个字段都要查字典。
FIX接入的几个关键点:
- 会话管理:FIX是长连接,需要维护SeqNum。我曾经因为SeqNum错乱,导致整个链路重连了半小时。
- 心跳机制:默认30秒一次心跳。如果连续3次没收到,就要触发重连。
- 日志记录:所有FIX消息必须落盘。出问题时,这是唯一的排查依据。
3.1.3 消息队列接入
消息队列是内部数据流转的「高速公路」。我们常用Kafka或RabbitMQ。
为什么需要消息队列?说白了,就是解耦。采集层只管收数据,处理层只管消费数据。中间用MQ缓冲,谁都不拖累谁。
| 特性 | Kafka | RabbitMQ |
|---|---|---|
| 吞吐量 | 百万级/秒 | 万级/秒 |
| 消息顺序 | 分区内有序 | 队列内有序 |
| 持久化 | 磁盘存储 | 内存+磁盘 |
| 适用场景 | 高吞吐、日志、行情 | 低延迟、任务分发 |
3.2 数据采集架构图
下面这张图是我自己项目里用过的架构。它把三大数据源统一接入,然后做标准化处理,最后写入Kafka供下游消费。
3.3 数据质量与异常处理
数据采集层最容易出问题的,不是「拿不到数据」,而是「拿到错误的数据」。
我曾经遇到一个场景:交易所API返回的行情数据,某只股票的价格突然跳了100倍。后来发现是交易所的bug,但我们的监控系统直接触发了虚假告警。
- 价格范围校验(比如不能为负,不能超过前值的10倍)
- 时间戳单调递增校验
- 重复数据去重(基于消息ID或时间戳)
3.4 性能优化要点
数据采集层往往是整个系统的瓶颈。我总结了几条优化经验:
- 批量处理:不要一条一条地发。攒够100条或100ms,批量写入Kafka。吞吐量能提升10倍。
- 零拷贝:如果使用Netty或Kafka,开启零拷贝模式。减少数据在内核态和用户态之间的拷贝。
- 异步非阻塞:所有I/O操作都用异步。别用同步阻塞,否则一个慢接口拖死整个采集线程。
- 内存池:高频场景下,频繁new对象会导致GC抖动。用对象池复用ByteBuf或Message对象。
3.5 总结
数据采集层,说白了就是「接进来、洗干净、送出去」。
接进来要兼容多源,洗干净要校验质量,送出去要高效可靠。这三个环节,任何一个出问题,监控系统就是「睁眼瞎」。
我个人建议,在设计阶段就把数据采集层的容错、限流、监控指标(比如采集延迟、丢失率)都考虑进去。别等到上线了再补,那时候就晚了。