2. 技术选型:实时计算三驾马车与存储矩阵
实时指标体系建设,技术选型是第一步。选错了,后面全是坑。我这些年见过太多团队,一上来就追新,结果运维成本爆炸,或者性能根本扛不住。今天咱们就掰开揉碎了聊聊,实时计算引擎、消息队列、存储系统到底怎么选。
核心原则:没有最好的技术,只有最合适的场景。选型前先问自己三个问题:数据量级多大?延迟要求多高?团队运维能力如何?
2.1 实时计算引擎:Flink vs Spark Streaming vs Storm
这三兄弟,我最早接触的是 Storm。那时候实时计算还是个新鲜玩意儿。后来 Spark Streaming 凭借生态优势火了一把。现在嘛,Flink 基本是事实标准了。但每个引擎都有它的用武之地。
| 维度 | Flink | Spark Streaming | Storm |
|---|---|---|---|
| 计算模型 | 真正的流处理(逐条处理) | 微批次(Mini-Batch) | 逐条处理 |
| 延迟 | 毫秒级 | 秒级(取决于批次间隔) | 毫秒级 |
| 状态管理 | 原生支持,强一致性 | 依赖外部存储 | 需自行实现 |
| Exactly-Once | 原生支持 | 支持(需配置) | 需自行实现 |
| SQL支持 | Table API / SQL 成熟 | Structured Streaming | 弱 |
| 运维复杂度 | 中等 | 低(与Spark批处理共用集群) | 高 |
Flink:实时指标的首选
我个人习惯,新项目直接上 Flink。为什么?因为它把「流」这件事想明白了。你想想看,数据本来就是一条一条来的,非要用微批次去模拟流,这不是脱裤子放屁吗?
Flink 的事件时间语义、Watermark 机制、状态后端,都是为实时指标量身定做的。我在做电商大促实时大屏时,Flink 扛住了百万 QPS 的点击流,延迟控制在 200ms 以内。换 Spark Streaming 的话,批次间隔至少得设 2 秒,那大屏数据就成「伪实时」了。
我的经验:如果团队对 Java/Scala 熟悉,且需要复杂事件处理(CEP)、精确一次语义,闭眼选 Flink。它的 Checkpoint 机制虽然配置起来有点麻烦,但一旦调好,故障恢复非常稳。
Spark Streaming:批流一体场景的备选
Spark Streaming 不是不能做实时,只是它骨子里是个批处理引擎。它的优势在于:如果你已经有 Spark 批处理任务,复用集群可以降低运维成本。延迟要求 3-5 秒以内的场景,它完全够用。
我记得有个金融客户,他们的实时风控系统用了 Spark Streaming。为什么?因为他们同时要做 T+1 的离线报表,一套 Spark 集群搞定,省了一堆机器。但要注意,微批次模型在处理乱序数据时比较吃力,需要配合事件时间窗口,配置起来比 Flink 复杂。
避坑指南:我曾经见过一个团队,用 Spark Streaming 做秒级聚合,批次间隔设了 500ms。结果集群资源消耗巨大,还经常 OOM。后来改成 2 秒批次,反而更稳。记住,Spark Streaming 的批次间隔不要低于 1 秒,否则得不偿失。
Storm:历史遗留的选择
Storm 是实时计算的「老前辈」。它的延迟确实低,但缺点也很明显:没有状态管理、没有 Exactly-Once、运维复杂。现在新项目基本不会选它了。除非你维护的是 5 年前的老系统,否则别碰。
2.2 消息队列选型:Kafka vs Pulsar
消息队列是实时指标的「血管」。数据从源头到计算引擎,全靠它传输。选型核心看三点:吞吐量、持久化、消费模型。
| 维度 | Kafka | Pulsar |
|---|---|---|
| 架构 | 分区日志模型 | 计算与存储分离 |
| 吞吐量 | 极高(百万级/秒) | 高(十万级/秒) |
| 消息持久化 | 磁盘顺序读写 | 分层存储(BookKeeper) |
| 消费模型 | 分区内有序 | 支持多种订阅模式 |
| 运维复杂度 | 中等 | 较高(组件多) |
| 生态 | 极其成熟 | 快速发展中 |
Kafka:实时指标的标配
Kafka 在实时指标领域,地位跟 Flink 差不多——事实标准。它的分区模型天然适配并行消费,吞吐量能轻松打到百万级。而且 Kafka 的生态太强了,Flink、Spark、各种 Connector 都优先支持它。
我做过一个日处理 10 亿条日志的实时指标系统,Kafka 集群就 6 台机器,稳如老狗。唯一要注意的是分区数规划——分区太多会导致文件句柄开销大,太少又影响并行度。我的经验是:分区数 = 目标吞吐量 / 单分区吞吐量 × 1.5 的冗余。
小技巧:Kafka 的消息体不要太大。我见过有人把整个 JSON 嵌套对象塞进去,结果序列化/反序列化成了瓶颈。建议控制在 1MB 以内,最好 100KB 左右。如果消息体大,考虑用 Avro 或 Protobuf 压缩。
Pulsar:云原生场景的潜力股
Pulsar 的优势在于计算存储分离。你可以独立扩缩容 Broker 和 BookKeeper 节点,资源利用率更高。而且它支持多种消费模式(独占、共享、灾备),灵活性比 Kafka 强。
但说实话,Pulsar 的运维门槛比 Kafka 高。它依赖 ZooKeeper 和 BookKeeper,组件多了,出问题的概率也大。我建议:如果团队有专门的中间件运维人员,且对云原生架构有需求,可以试试 Pulsar。否则,Kafka 更稳妥。
避坑指南:我曾经在一个 Pulsar 集群上踩过坑——BookKeeper 的 Journal 磁盘写满了,导致整个集群写入阻塞。后来加了监控和磁盘告警才解决。Pulsar 的磁盘规划比 Kafka 更敏感,一定要预留足够的 Buffer。
2.3 存储选型:HBase vs ClickHouse vs Redis
存储是实时指标的「终点」。数据算完了,得存起来,供查询和展示。不同的指标类型,适合不同的存储。
| 维度 | HBase | ClickHouse | Redis |
|---|---|---|---|
| 数据模型 | 宽表、稀疏矩阵 | 列式存储 | 键值对 |
| 写入性能 | 高(LSM-Tree) | 极高(批量写入) | 极高(内存操作) |
| 查询性能 | 中等(按 RowKey 查询快) | 极高(聚合查询) | 极高(点查) |
| 适用场景 | 明细数据存储、时序数据 | OLAP 分析、大屏聚合 | 缓存、计数器、排行榜 |
| 数据量 | PB 级 | TB ~ PB 级 | GB ~ TB 级(受内存限制) |
HBase:海量明细数据的归宿
HBase 适合存「原始明细」和「宽表」。比如用户行为日志、订单流水,每条数据几十个字段,用 HBase 的稀疏矩阵模型存,非常省空间。它的 LSM-Tree 写入模型,能轻松扛住每秒几十万的写入。
但 HBase 的查询能力偏弱。你只能按 RowKey 或者 RowKey 范围查,想做复杂的聚合分析?别想了。我一般把 HBase 作为「数据湖」的实时层,明细数据先落 HBase,再通过 ClickHouse 做物化视图。
我的习惯:RowKey 设计是 HBase 的灵魂。我通常把「时间戳取反 + 业务ID」作为 RowKey,这样最新数据能分散到不同 Region,避免热点。记住,HBase 最怕的就是 RowKey 单调递增,那会导致所有写请求打到一个 Region 上。
ClickHouse:实时聚合查询的利器
ClickHouse 是我做实时指标最常用的存储。它的列式存储和向量化执行引擎,让聚合查询快得离谱。一个 10 亿行的表,做 Group By 加 Count,秒级出结果。
我做过一个实时大屏,Flink 每 10 秒写入一次聚合结果到 ClickHouse,前端查询延迟基本在 100ms 以内。ClickHouse 的 ReplacingMergeTree 和 AggregatingMergeTree 引擎,简直就是为实时指标设计的。
避坑指南:ClickHouse 不适合高频点查。它的 MergeTree 引擎在查询单行时,需要扫描整个分区,性能很差。如果你需要「查某条具体数据」,别用 ClickHouse,用 HBase 或者 Redis。另外,ClickHouse 的并发查询数有限,建议前面加一层查询缓存(比如 Redis 或 Proxy)。
Redis:缓存与计数器的王者
Redis 在实时指标里,主要干三件事:缓存、计数器、排行榜。它的内存操作速度是纳秒级的,适合对延迟极度敏感的场景。
比如实时 UV 去重,用 Redis 的 HyperLogLog,占用 12KB 内存就能统计上亿的独立用户。再比如实时排行榜,用 Redis 的 Sorted Set,插入和查询都是 O(logN)。
但 Redis 的短板也很明显——数据量受内存限制。你不可能把所有明细数据都放 Redis 里。我一般把 Redis 作为「热数据」层,存最近 1 小时的聚合结果,历史数据放 ClickHouse 或 HBase。
小技巧:Redis 的 Pipeline 和 Lua 脚本能大幅提升批量操作性能。我在做实时计数器时,用 Lua 脚本把「读-改-写」操作原子化,避免了并发竞争。另外,别忘了设置过期时间,不然 Redis 内存迟早爆掉。
2.4 技术选型全景图
说了这么多,咱们用一张图把整个选型逻辑串起来。这张图是我做实时指标系统时的「选型地图」,照着它走,基本不会跑偏。
这张图从左到右,就是一条完整的实时指标数据流。数据从源头进来,经过消息队列缓冲,交给计算引擎处理,最后落到不同的存储里。每一层都有明确的选型建议。
总结一下我的选型心法:
- 计算引擎:新项目无脑 Flink。除非你已经有 Spark 集群且延迟要求不高。
- 消息队列:Kafka 是标配。Pulsar 适合云原生且运维能力强的团队。
- 存储:明细用 HBase,聚合用 ClickHouse,热数据用 Redis。三者配合,天下无敌。