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 技术选型全景图

说了这么多,咱们用一张图把整个选型逻辑串起来。这张图是我做实时指标系统时的「选型地图」,照着它走,基本不会跑偏。

实时指标技术选型全景图 数据源层 业务日志 | 埋点数据 | 数据库Binlog | IoT传感器 消息队列层 Kafka(首选) | Pulsar(云原生场景) 实时计算引擎层 Flink(首选) | Spark Streaming(批流一体) | Storm(遗留系统) 存储层 HBase(明细) | ClickHouse(聚合分析) | Redis(缓存/计数器) 应用层 实时大屏 | 实时告警 | 实时报表 | 实时推荐 选型口诀:数据进Kafka,计算用Flink,明细存HBase,聚合查ClickHouse,热数据放Redis

这张图从左到右,就是一条完整的实时指标数据流。数据从源头进来,经过消息队列缓冲,交给计算引擎处理,最后落到不同的存储里。每一层都有明确的选型建议。

总结一下我的选型心法:

  • 计算引擎:新项目无脑 Flink。除非你已经有 Spark 集群且延迟要求不高。
  • 消息队列:Kafka 是标配。Pulsar 适合云原生且运维能力强的团队。
  • 存储:明细用 HBase,聚合用 ClickHouse,热数据用 Redis。三者配合,天下无敌。