后台数据采集业务设计
后台数据采集业务设计
数据采集(主要是数据收集)作为核心需求,常出现在日志系统、图表统计项目等的实现中:

由于其数据和展示形式的多样性,不同的场景下我们选择的技术、部门、架构体系等需要进行求同存异的取舍;比方说公司中有大数据部门或相关人员,则可把数据采集与展示拆分成两个需求给两方开发。比如数据简单,展示轻松,则是一端的简单处理等等...
不过我在实际开发与研讨中发现,数据采集业务在设计开发前期一定存在几个阶段,感觉和往昔探索直播间弹幕系统的设计各个阶段一样(快速实现、扩展、优化、未来),系统开发的难度会随着数据量及需求的复杂化而逐渐增加。
因此本篇记录本人在查阅互联网上相关信息及自身体验,探讨一次一个数据采集系统应该如何设计;
采集什么
采集需求在传统软件中大体分为三类:
- 用户行为分析与交互数据采集
- 物联网的设备数据采集
- 时序内容数据采集(比如人口统计、金融数据分析等等...)
参考目前市面上的案例:
运维检测系统:来自apache
的 hertzbeat ,作为一个以采集运维数据(系统变量,工具性能...)生成看板的项目,是一个标准的内容数据采集系统
运动手环的睡眠质量图:也是小米手环通过物联网IOT的上报链路,采集睡眠质量数据,生成图表的功能,是一个标准的物联网的设备数据采集场景
...
目标
基本所有的数据采集的系统最终给用户展示的结果都是一张"大表";比方说实时监控大屏、日志平台、图表报表等等...
这些"大表"在不同程度上有着相同的核心矛盾点:高吞吐 vs 低延迟 vs 数据一致性
而我们的目标即是在三者中找到一个平衡点,高性能的执行我们的采集背景
例如在不同场景的优先级差异:
- 用户行为数据(如埋点日志):高吞吐、最终一致性
- 物联网设备数据:实时性、时序性
- 时序内容数据(如金融统计):强一致性、准确性
因此在定义一个数据采集系统的第一步,一定是结合业务本身判断我们做的系统是重一致性的还是重吞吐或是要求实时性,不同的选择直接影响了数据消息链路的走向。
定义了系统后,就可以明确目标了:
- 需要一个高实时性的实时监控系统
- 需要一个数据准确的内容分析系统
- 需要一个支持大用户量的用户描点系统
- ...
选型
主要指中间件的选择,这一点不同人不同公司都有各自的喜好,所以这里只举例说明现市场上各种在数据采集系统中可能出现的技术中间件
消息中间件对比
中间件 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
Kafka | 高吞吐日志、流处理 | 分区有序、持久化、生态完善 | 运维复杂、延迟较高 |
Pulsar | 实时设备数据流 | 低延迟、分层存储、多租户 | 社区生态较小 |
MQTT | IoT 设备低功耗通信 | 轻量级、支持 QoS 分级 | 不适合复杂业务 |
Redis | 实时看板、简单队列 | 超低延迟、数据结构丰富 | 数据持久化弱 |
RabbitMQ | 小数据、并发度不高 | 协议灵活、易于部署 | 大数据场景性能偏弱 |
数据库选型
数据库是数据采集系统的核心存储层,需根据数据类型、查询模式和一致性需求选择:
关系型数据库
适用场景:
- 强一致性要求(如金融统计、用户账户数据)
- 复杂事务支持(如订单状态更新)
选型对比:
数据库 优势 缺点 MySQL 生态成熟、ACID 支持 单表性能瓶颈 PostgreSQL JSONB 支持、地理空间数据 高并发写入略弱 Oracle 性能强,稳定性高 授权费用,维护复杂
时序数据库
适用场景:
- IoT 设备数据(温度、湿度等时序指标)
- 监控指标存储(如服务器 CPU、内存)
选型对比:
数据库 优势 缺点 InfluxDB 高性能写入、时间窗口聚合 开源版无集群支持 TDengine 高压缩率、开源分布式 生态工具较少 TimescaleDB 基于 PostgreSQL 的时序扩展,是关系型时序数据库 写入性能略低于专有时序库 IOTDB 免费支持集群,性能强大,国产之星 生态不完善,功能相比稍显不足
文档数据库
适用场景:
- 半结构化日志存储(如用户行为日志)
- 动态文档数据(如设备元数据)
选型对比:
数据库 优势 缺点 MongoDB 灵活 Schema、分片易用、部分更新 事务性能较低(基本没有) Elasticsearch 全文检索、聚合分析强 写入吞吐受限
列式数据库
- 适用场景:
- 海量离线数据分析(如用户画像计算)
- 高压缩比存储(如历史日志归档)
- 选型示例:
- Apache HBase:强一致、适合实时读写
- Apache Cassandra:最终一致、适合高可用写入
K-V数据库
- 适用场景
- 实时看板(如 PV/UV 实时统计)
- 高速缓存(如热点设备数据)
- 选型示例:
- Redis:数据结构丰富、持久化可选
大数据工具
因为本人对大数据相关技术不能说没有把,只能说云 😥,所以以下为AI的回答:
来自豆包:
框架 | 适用场景 | 特点 |
---|---|---|
Apache Flink | 实时流处理、精确一次语义 | 低延迟、高吞吐 |
Apache Spark | 批处理、机器学习 | 生态完善、容错性强 |
Kafka Streams | 轻量级流处理(Kafka 生态) | 无需额外集群、Exactly-Once |
实现
快速实现 (最小可行产品)架构
相比于其他系统的快速实现思路,数据采集的快速实现思路,更加的暴力;
在项目初期,在快速上线,数据体量下的背景下。由于不需要考虑数据量、并发度、丢失等等客观因素,我们的系统可以设计为一个简单的异步削峰消费模式下的数据收集器。
因此在结构上尽量的简洁,链路直达式的入库:
比如在采集用户行为的系统中,我们的发送方代码通过埋点的方式:
@Aspect
@Component
public class UserBehaviorAspect {
@Around("execution(* com.example.controller.*.*(..))")
public Object track(ProceedingJoinPoint pjp) throws Throwable {
// 构建埋点事件
// 发送到 Kafka
streamBridge.send("user-behavior-topic", JSON.toJSONString(event));
return result;
}
}
数据传输层则可使用 Spring Cloud Stream
处理方则是使用批处理框架Spring batch
,完成对数据的一次聚合最终入库
最终只需要对数据库进行简单的索引查询优化,一个简单的快速实现的数据采集完成了,是不是更像是一个简单的数据收发的系统;
技术组合下来常选择:
- 采集层:Spring Boot 切面埋点 / Netty(设备接入)
- 传输层:Kafka(单节点快速部署)
- 存储层:MySQL + MyBatis-Plus(快速 CRUD)
- 展示层:接口
数据采集系统的快速实现阶段并不适用于所有类型的系统,往往一个最简单的采集都有着不小的数据量,因此很多系统的实现思路都会跳过这一阶段;
扩展
随着数据量的增大,采集系统一定面临着以下问题:
- 一秒并发
- 流量损耗,流量带宽
- 热点时间数据量突增
- 读写查询效率问题
- 数据丢失
- ....
简单的异步数据收发器无法解决上述问题,所以必须要从功能、水平、垂直方向分别进行系统架构的扩展
功能扩展
鲁迅说过:如果一个中间件不够,就多加几个中间件
**1) **首先是解决并发的问题:
采用Kafka+采集任务调度的方式,调度器直接桥接来自kafka的数据;调度器作为指挥塔判断数据是否聚合,根据什么聚合,比如时间窗口/阈值/类型....,完成第一次聚合后分组分发给不同的采集器;
这样入口接收的并发问题通过数据聚合加分流分发的方式足以解决大半,剩下的交给机器
**2)**流量损耗,流量带宽
流量带宽是数据采集传输过程中无法规避的问题,假设一个数据包1KB,一天十万数据包对于系统来说是很小的数据量,流量也会超乎想象;
所以我们只能做到:
- 尽可能切换内网
- 压缩算法选择:GZIP、ZSTD、 LZ4 、 Snappy 的压缩效率平衡
- 采用Parquet格式减少IO
**3)**热点数据突增问题:
在数据传输层上增加buffer,控制数据到处理层的流动速度,当速度达到热点阈值时监控系统发起报警,执行脚本:修改线程优先级
优先采集器的线程处理,先将采集到的数据塞到数据传输层,由数据传输层进行速率控制;
数据传输层判断传输给窗口聚合器的条件是否支持当前速率,将多余部分直接推入直推模式的系统中。
这样通过优先接收,减缓处理的方式处理突增大批的数据,可以以空间换时间的思路解决
**4)**读写查询问题
1、列式存储的数据库(实时性要求高的业务)
2、常规的数据库主从配置,读写分离
3、表和缓存的查询设计,以展示点-面图表为简单例子:
在点面图表需求中,多是X轴为时间 秒/分/时/...,Y轴为具体值。
在查询时,数据库中存储的是point-value的值,例如按秒查询字段:
时间x | 值value |
---|---|
yyyy-MM-dd HH:mm:ss | 1 |
yyyy-MM-dd HH:mm:ss | 2 |
按分查询(聚合秒数据后)
时间x | 值value |
---|---|
yyyy-MM-dd HH:mm | 1 |
yyyy-MM-dd HH:mm | 2 |
而按时/月/...更大的查询,则不进行数据库查询,转而由缓存兜住改动,后续再进行定时入库
这样就分成了,秒级查询取决于数据库能力(没有办法),秒以上,则是已经被聚合计算过的数据,跨度大的数据则交由缓存能力;
所以总结是:
- 多级缓存架构:Guava Cache -> Redis -> 数据库
- 预聚合策略:使用物化视图预先计算常用维度
5) 数据丢失问题
数据丢失是大数据处理中非常棘手的问题,如果是时效性不强的业务还好,一旦要求了一定的时效性,那么对于数据丢失问题则需要分类讨论:
- 数据丢失重新消费
- 数据丢失 ,不做处理
- 数据丢失,视图层补偿
- ...
至于处理方式,常规的消息丢失的处理模式可以支撑
参考图(简单架构)
垂直扩展策略
得加钱😶
水平扩展策略
模块 | 扩展方案 |
---|---|
采集层 | 外置调度中心,水平扩展采集器节点数 |
消息队列 | Kafka 分区扩容 + 消费者组 |
存储层 | 分库分表,从机+++ |
计算层 | Flink 并行度调整,Flink节点+++ |
优化
又随着数据量的增大,并发波动;
无底线的扩展当然不是我们想要看到的,也因此需要可以应对最坏情况的容灾机制;
故障类型 | 检测机制 | 恢复策略 |
---|---|---|
节点宕机 | 心跳检测+ZooKeeper探活 | 自动切换备用节点 |
网络分区 | 时钟偏移检测 | 进入降级模式,本地缓存数据 |
数据损坏 | CRC32校验+版本号 | 从最近检查点恢复+人工干预 |
突发流量 | Prometheus指标监控 | 动态限流+自动扩容 |
当性能达到瓶颈时,则需要考虑大数据工具和框架的介入,毕竟数据采集业务始终是一个大数据业务,上述都是基于常规的后台系统的背景下的讨论。
还可以引入更多的技术进行优化拓展
- AI驱动的数据质量管理:自动检测异常模式
- 动态Schema演进:支持无服务中断的字段变更
- 边缘计算集成:在数据上报端进行初步数据处理
结语
这篇文章的诞生背景是因为我手上的某个需求,随着产品的添油加醋变更需求,从快速实现中简单粗暴的架构就可以支持功能的正常运行,到数据量把数据采集者撑爆😂。也是一步步的解決文中提到的问题,到了拓展阶段。
开发路上看起来平平无奇,到上线数据量实际打过来的时候,还是发现有非常多没有考虑到的点;以及本篇文章也并没有去延伸数据采集开发中会遇到的坑(感觉可以单独开一篇)
最后提一句,数据采集一定是 大数据 数据,而本文其实并不是从大数据工程师的角度上讨论(因为没学过),如果你是后台工程师,那么大概率要设计的是数据发送方的数据处理问题。