实时数据技术栈概览:消息队列、计算引擎、存储与查询

这一章,我们来聊聊实时数据产品的技术底座。说白了,就是数据从产生到被消费,中间经过的那些核心组件。我见过不少团队,业务逻辑写得飞起,但技术选型一塌糊涂,最后系统跑不起来。嗯,这里头是有门道的。

实时数据技术栈,我习惯把它拆成四个层次:消息队列、实时计算引擎、实时存储、查询与可视化。每一层都有它的代表作,也有它的适用场景。我们一个一个来看。

核心观点:实时数据技术栈不是大杂烩,而是一套经过实战检验的组合拳。选型的关键在于理解每个组件的设计哲学和边界。

消息队列:数据的「高速公路」

消息队列是实时数据的入口。没有它,上游系统直接怼到下游,一旦流量波动,整个链路就崩了。我最早做实时项目时,就吃过这个亏——业务方直接写数据库,高峰期把库打挂了。后来才明白,消息队列不只是「传数据」,更是「削峰填谷」的缓冲层。

目前业界最主流的选择是 Apache Kafka。为什么是它?

  • 高吞吐:单机每秒能处理几十万条消息。我实测过,三台 broker 的集群,扛住百万级 QPS 没问题。
  • 持久化:消息落盘,不会丢。你可以配置保留策略,比如保留 7 天,随时回溯。
  • 分区与副本:分区实现并行消费,副本保证高可用。你想想看,一个分区挂了,副本自动顶上,业务无感知。

但 Kafka 也不是万能的。它不适合小消息、低延迟的场景。如果你每条消息只有几十字节,但要求毫秒级延迟,Kafka 的批处理机制反而成了瓶颈。这时候,Redis Stream 或 Pulsar 可能是更好的选择。

我的经验:Kafka 的分区数不是越多越好。分区太多,会导致文件句柄暴增、Leader 选举变慢。我一般建议分区数不超过 broker 数量的 10 倍。

实时计算引擎:数据的「加工厂」

数据进了消息队列,接下来要处理。实时计算引擎就是干这个的。它把无界的数据流,按照业务逻辑进行转换、聚合、关联。

这个领域,Apache Flink 是当之无愧的王者。为什么?

  • 真正的流式计算:Flink 从设计之初就是为流而生,而不是像 Spark Streaming 那样用微批模拟流。这意味着,Flink 的延迟更低,能做到真正的「事件驱动」。
  • 精确一次语义:这是实时计算的「圣杯」。Flink 通过 Checkpoint 和两阶段提交,保证数据不重不丢。我曾经在金融项目中,靠这个特性通过了审计。
  • 强大的状态管理:实时计算离不开状态——比如统计过去 5 分钟的点击量。Flink 提供了 RocksDB、HashMap 等多种状态后端,你可以根据内存和性能要求灵活选择。

Flink 的编程模型也很直观。你只需要定义 Source、Transformation、Sink 三个部分。举个例子:

// 从 Kafka 读取数据
DataStream<String> stream = env.addSource(
    new FlinkKafkaConsumer<>("topic", new SimpleStringSchema(), properties)
);

// 每 5 秒统计一次单词频率
stream
    .flatMap(new Tokenizer())
    .keyBy(value -> value.f0)
    .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
    .sum(1)
    .addSink(new MyRedisSink());

env.execute("实时词频统计");

你看,代码很简洁。但实际项目中,坑往往在细节里——比如 Checkpoint 超时、背压处理、状态后端调优。这些我们后面会专门讲。

避坑指南:我曾经在一个项目中,Flink 作业跑着跑着就 OOM 了。查了半天,发现是状态没有配置 TTL(生存时间)。状态越积越多,内存撑爆了。记住:所有状态都要设置合理的 TTL。

实时存储:数据的「落脚点」

计算完了,数据要存起来。实时存储和离线存储不一样,它要求低延迟、高并发、支持点查。没有一种存储能包打天下,你得根据场景选。

我整理了一张对比表,方便你快速决策:

存储引擎 核心特点 适用场景 不适用场景
HBase 列式存储,海量数据,随机读写 用户画像、订单明细、日志存储 复杂聚合、多维度分析
Redis 内存型,毫秒级延迟,丰富数据结构 缓存、计数器、排行榜、Session 海量数据持久化、复杂查询
ClickHouse 列式存储,极速分析,支持 SQL 实时报表、OLAP 分析、监控看板 高频点查、单行更新

说说我的用法:

  • HBase:适合存「大表」——比如用户行为日志,每天几十亿条。它的 RowKey 设计很关键,设计不好就是全表扫描。我一般用「盐值 + 时间戳」打散热点。
  • Redis:适合存「热数据」——比如实时排行榜、用户在线状态。注意,Redis 的持久化能力弱,别把它当数据库用。我习惯用 Redis 做缓存层,HBase 做持久层。
  • ClickHouse:适合做「分析」——比如实时大屏、BI 报表。它的查询速度极快,但写入是批量追加的,不适合频繁更新。我一般在 Flink 中做预聚合,然后批量写入 ClickHouse。

我的建议:不要试图用一个存储解决所有问题。实时系统往往是「混合存储」架构——Redis 扛热数据,HBase 存全量,ClickHouse 做分析。各司其职,才是正道。

实时查询与可视化:数据的「最后一公里」

数据存好了,怎么让业务方看到?这就是查询与可视化的活。实时查询和离线查询不一样,它要求秒级响应,甚至亚秒级。

常见的查询方式有两种:

  1. API 查询:业务系统通过 HTTP 或 RPC 接口,直接查实时存储。比如查某个用户的实时积分。这种场景,Redis 或 HBase 的 API 就够用了。
  2. 可视化看板:用图表展示实时数据,比如实时大屏、监控面板。这种场景,需要专门的工具。

可视化工具方面,我常用的有:

  • Grafana:开源、插件丰富,支持 ClickHouse、Prometheus 等多种数据源。我习惯用它做运维监控和业务看板。
  • Superset:Apache 孵化项目,支持 SQL 查询,适合做 BI 分析。如果你团队熟悉 SQL,Superset 上手很快。
  • 自建 Web 应用:如果业务逻辑复杂,比如需要交互式下钻,我会用 Node.js 或 Java 写一个轻量级 API 层,前端用 ECharts 或 AntV 渲染。

你想想看,一个实时大屏背后,数据流是这样的:

业务系统 → Kafka → Flink 计算 → ClickHouse 存储 → Grafana 查询 → 大屏展示

每一步的延迟都要控制在毫秒到秒级,才能保证大屏的「实时感」。我曾经见过一个项目,Flink 算得很快,但 ClickHouse 查询慢,导致大屏数据延迟了 10 秒。最后发现是表引擎选错了,换成 ReplicatedMergeTree 后,查询时间从 5 秒降到了 200 毫秒。

注意:实时查询不是「越快越好」。如果业务方只需要分钟级延迟,你用 Flink + ClickHouse 就是杀鸡用牛刀。这时候,直接用 Kafka + 定时任务 + MySQL 可能更划算。技术选型,永远要回归业务需求。

一张图看懂实时数据技术栈

说了这么多,我画了一张架构图,帮你把整个链路串起来。这张图是我做项目时常用的「技术栈全景图」,你可以把它贴在工位上。

实时数据技术栈全景图 数据源(App / 服务 / IoT) 消息队列(Kafka) 实时计算(Flink) 实时存储(HBase / Redis / ClickHouse) 查询与可视化(Grafana / API) 核心原则 削峰填谷 流批一体 混合存储 关键指标 延迟:毫秒 ~ 秒级 吞吐:百万级 QPS 一致性:精确一次

这张图里,数据从下往上流。每一层都有明确的职责,层与层之间通过标准接口解耦。你想想看,如果有一天你想把 Kafka 换成 Pulsar,只要不改 Flink 的 Source 逻辑,其他层完全不受影响。这就是分层设计的好处。

小结

实时数据技术栈,说白了就是四个组件:Kafka 负责传、Flink 负责算、HBase/Redis/ClickHouse 负责存、Grafana 负责看。每个组件都有自己的强项和短板,没有银弹。

我个人习惯,在项目启动前先画一张类似上面的架构图,把每一层的选型和边界定清楚。这样,后面开发的时候就不会跑偏。嗯,这一章的内容就到这里。记住:技术栈是工具,业务才是目的。选型之前,先想清楚你要解决什么问题。