2、核心技术栈选型:消息队列、流处理框架、存储引擎

好,咱们接着聊。上一章我们把数据回放系统的整体架构搭起来了,现在要往里面填真正的「零件」了。

这一章,我带你过一遍最核心的三个技术选型:消息队列、流处理框架、存储引擎。说白了,就是决定数据怎么传、怎么算、怎么存。

这三个选型一旦定下来,后面80%的代码结构就跟着走了。所以,咱们得慎重。

核心结论先放这:

  • 消息队列:中小规模选 Kafka,大规模低延迟选 Pulsar
  • 流处理框架:实时性要求高选 Flink,批流一体选 Spark Streaming
  • 存储引擎:热数据用本地 SSD,冷数据上 S3,归档用 HDFS

2.1 消息队列:Kafka vs Pulsar

消息队列是整个系统的「血管」。数据从采集端进来,先到消息队列,再被下游消费。选不好,要么吞吐上不去,要么延迟下不来。

Kafka:老牌王者

Kafka 我用了很多年。它的设计哲学很纯粹——顺序写磁盘,利用操作系统的 Page Cache 来加速读写。你想想看,一个普通的机械硬盘都能跑到几百 MB/s 的吞吐,这就是 Kafka 的底气。

我个人习惯用 Kafka 的场景是:

  • 数据量在每天几十 TB 以内
  • 对消息顺序有严格要求
  • 团队对 Kafka 运维比较熟悉

举个例子,我之前做一个金融交易回放系统,每天大概 5TB 的行情数据。Kafka 集群 6 台机器,单分区吞吐能到 50MB/s,延迟在 10ms 以内。完全够用。

避坑指南:我曾经在 Kafka 上踩过一个坑——分区数设得太多。当时为了追求并行度,一口气设了 128 个分区。结果呢?Leader 选举慢、文件句柄爆满、GC 频繁。后来我学乖了,分区数一般控制在 Broker 数量的 3~5 倍。

Pulsar:后起之秀

Pulsar 是后来才火起来的。它的核心创新是「存算分离」——Broker 只管计算,数据存在 BookKeeper 里。这样做的好处是:

  • 扩缩容非常快,不需要重平衡数据
  • 支持多租户,资源隔离做得好
  • 延迟更低,尤其是尾延迟

我建议在以下场景考虑 Pulsar:

  • 数据量达到每天几百 TB 级别
  • 需要毫秒级端到端延迟
  • 多个团队共享同一个集群

嗯,这里要注意:Pulsar 的运维复杂度比 Kafka 高。BookKeeper 的配置调优、故障恢复,都需要更深的功底。

对比维度 Kafka Pulsar
架构 存算一体 存算分离
吞吐 高(单机可达 1GB/s) 高(水平扩展更优)
延迟 10ms 级别 1ms 级别
运维复杂度 中等 较高
社区生态 非常成熟 快速发展中

2.2 流处理框架:Flink vs Spark Streaming

消息队列里的数据,需要被「加工」才能变成可回放的形式。这就是流处理框架的活。

Flink:真正的实时

Flink 的设计理念是「每条数据来了就处理」,而不是攒一批再处理。这听起来理所当然,但实现起来非常难。

我在项目中遇到过这样一个场景:需要做 5 秒的滑动窗口统计,计算过去 1 小时内每 5 秒的成交量。用 Flink 的 EventTime 和 Watermark 机制,代码写起来很自然:

DataStream<Trade> trades = env.addSource(kafkaConsumer);

trades
  .keyBy(trade -> trade.symbol)
  .window(SlidingEventTimeWindows.of(Time.hours(1), Time.seconds(5)))
  .aggregate(new VolumeAggregator())
  .addSink(redisSink);

Flink 的 Checkpoint 机制也很靠谱。有一次集群挂了 3 台机器,恢复后数据一条没丢,时间戳完全对齐。嗯,这一点 Spark Streaming 做不到。

注意:Flink 的 State 管理是个双刃剑。用好了性能极佳,用不好内存直接爆掉。我建议给每个算子设置 State TTL,别让状态无限增长。

Spark Streaming:批流一体

Spark Streaming 本质上是「微批处理」——把流切成一个个小批次,每个批次用 Spark 的批处理引擎来算。

它的优势在于:

  • 和 Spark 生态无缝集成(MLlib、GraphX 等)
  • 处理逻辑和批处理完全一致
  • 对乱序数据的处理更简单

但缺点也很明显:延迟至少几百毫秒,做不到真正的「实时」。

我个人习惯:如果业务能接受 1~5 秒的延迟,而且团队已经熟悉 Spark,那就用 Spark Streaming。否则,还是 Flink 更香。

对比维度 Flink Spark Streaming
处理模式 逐条处理 微批处理
延迟 毫秒级 秒级
Exactly-Once 原生支持 需要配置
状态管理 强大(ValueState、MapState 等) 较弱(依赖外部存储)
生态集成 中等 丰富(Spark 全家桶)

2.3 存储引擎:HDFS vs S3 vs 本地 SSD

数据加工完了,要存起来。存储选型决定了回放的速度和成本。

本地 SSD:热数据的首选

如果你需要毫秒级的回放延迟,本地 SSD 是唯一的选择。我做过测试,NVMe SSD 的随机读延迟在 0.1ms 以内,顺序读带宽能到 3GB/s。

但本地 SSD 的缺点是:

  • 容量有限(单机一般 2~8TB)
  • 机器挂了数据就丢了(除非做 RAID)
  • 成本高(每 GB 约 1~2 元)

所以,我一般只把最近 1~3 天的「热数据」放在本地 SSD 上。

S3:冷热数据的平衡点

S3 的延迟在 10~50ms 级别,比 SSD 慢,但比 HDFS 快。而且它几乎无限容量,按量付费。

我建议把 3 天到 3 个月的数据放在 S3 上。回放时虽然慢一点,但成本只有 SSD 的 1/10。

小技巧:我曾经用 S3 Select 来加速数据过滤。比如只回放某只股票的数据,S3 Select 可以在服务端过滤掉 90% 的数据,只传输需要的部分。回放速度能快 5~10 倍。

HDFS:归档存储

HDFS 适合存 3 个月以上的历史数据。它的吞吐很高,但延迟也高(100ms 以上)。

说实话,现在 HDFS 的地位有点尴尬。S3 在成本和易用性上都优于 HDFS,除非你已经有现成的 Hadoop 集群,否则我不建议新项目上 HDFS。

对比维度 本地 SSD S3 HDFS
延迟 <1ms 10~50ms 100ms+
吞吐 高(单机 3GB/s) 中(单连接 100MB/s) 高(集群 10GB/s+)
容量 有限(TB 级) 无限 大(PB 级)
成本 高 中 低
适用场景 热数据(1~3 天) 温数据(3 天~3 月) 冷数据(3 月以上)

2.4 整体选型框架

说了这么多,咱们用一张图来总结一下整个选型逻辑:

数据回放系统核心技术栈选型框架 数据源 消息队列 Kafka(成熟稳定) vs Pulsar(低延迟) 流处理框架 Flink(真正实时) vs Spark Streaming(批流一体) 存储引擎 本地SSD(热) → S3(温) → HDFS(冷) 数据回放服务

这张图展示了数据从采集到回放的完整链路。每个环节的选型都直接影响下一环节的性能和成本。

我的建议:别追求「最好的技术」,要追求「最适合的技术」。如果你的数据量只有每天几百 GB,Kafka + Flink + 本地 SSD 的组合完全够用,别为了炫技上 Pulsar 和 S3,徒增运维成本。

好了,核心技术栈的选型就聊到这里。下一章我们开始动手搭建开发环境,把今天选的这些组件真正跑起来。

可可精品资料库