2. 核心技术选型:实时计算引擎、特征存储与消息队列的对比

做实时特征平台,说白了就是选三样东西:算得快不快、存得对不对、传得稳不稳。这三样分别是实时计算引擎、特征存储和消息队列。我这些年踩过的坑,十有八九都跟选型有关。今天咱们就掰开揉碎了聊聊。

核心观点:没有最好的技术,只有最合适的场景。选型前先问自己三个问题——数据量级多大?延迟要求多高?团队熟悉什么栈?

2.1 实时计算引擎:Flink vs Spark Streaming

实时计算引擎是特征平台的“大脑”。目前主流就两个:Flink 和 Spark Streaming。我个人的习惯是,新项目优先考虑 Flink,但这不是的。

2.1.1 核心差异对比

对比维度 Apache Flink Spark Streaming
计算模型 真正的流式计算(逐条处理) 微批次(Micro-Batch)
延迟 毫秒级(< 100ms) 秒级(通常 1-10s)
状态管理 原生强状态(ValueState/MapState) 依赖外部存储(如 Redis)
Exactly-Once 语义 原生支持,轻量级 支持,但依赖事务写入
SQL 支持 成熟,动态表概念 较成熟,但微批次语义有局限
社区活跃度 极高,阿里主导 高,Databricks 主导

为什么会这样?Flink 的设计哲学是“流就是流”,每条数据来了就处理,不攒批。Spark Streaming 则是把流切成一个个小批次,再跑批处理逻辑。你想想看,如果业务要求 200ms 内出特征,Spark Streaming 基本没戏。

我的经验:做风控特征时,延迟要求 500ms 以内,我选了 Flink。做离线特征回刷时,用 Spark 批量处理历史数据,两个引擎配合使用,各取所长。

2.1.2 选型决策树

我一般按这个逻辑来选:

  1. 延迟要求 < 1s? → 选 Flink,没商量。
  2. 延迟 1-5s 可接受? → 看团队。熟悉 Java/Scala 选 Flink,熟悉 Python/SQL 选 Spark。
  3. 需要复杂状态管理? → Flink 原生状态比 Spark 方便太多。
  4. 批流一体需求? → Flink 1.12+ 已经做得不错,但 Spark 的批处理生态更成熟。

避坑指南:我曾经在一个项目里强行用 Spark Streaming 做毫秒级特征计算,结果调优调了两个月,最后还是切到了 Flink。记住,架构选型上的妥协,最终都会变成技术债。

2.2 特征存储:Redis vs HBase

特征存储是实时特征平台的“肌肉”。特征算出来得存着,而且要能快速读取。我见过不少团队在这上面栽跟头。

2.2.1 核心差异对比

对比维度 Redis HBase
数据模型 Key-Value,支持多种数据结构 宽表,列族存储
读写延迟 微秒级(内存操作) 毫秒级(依赖 HDFS 和 WAL)
存储容量 受内存限制(可加 SSD 缓存) PB 级,依赖 HDFS
持久化 RDB/AOF,但非强一致 强一致,HDFS 多副本
TTL 过期 原生支持,性能极好 需自己实现 TTL 机制
运维复杂度 低,主从/集群模式简单 高,需要 HDFS/ZK/HBase 全家桶

说白了,Redis 适合小数据量、高并发、低延迟的场景。HBase 适合大数据量、稀疏特征、需要强一致的场景。

我的建议:特征存储不要只用一种。我习惯用 Redis 做在线特征缓存(热数据),HBase 做全量特征存储(温冷数据)。这样既保证了读取速度,又解决了容量问题。

2.2.2 实际场景选择

  • 用户画像特征(用户数 < 1亿,特征维度 < 1000):Redis Cluster 足够。
  • 物品特征(物品数 > 10亿,特征稀疏):HBase 更合适。
  • 实时统计特征(如近 5 分钟点击量):Redis 的 Sorted Set 或 Hash 很方便。
  • 历史行为序列(需要扫描多行):HBase 的 Scan 操作比 Redis 高效。

小技巧:Redis 的 Pipeline 和 Lua 脚本可以大幅提升批量读写性能。我在做特征拼接时,经常用 Lua 脚本一次读取多个特征,减少网络开销。

2.3 消息队列:Kafka 的核心地位

消息队列是实时特征平台的“血管”。数据从产生到消费,全靠它来传输。说实话,在实时特征这个领域,Kafka 基本是事实标准。

2.3.1 为什么是 Kafka?

特性 Kafka Pulsar RocketMQ
吞吐量 极高(百万级 msg/s) 高(存算分离) 高(十万级 msg/s)
消息顺序 分区内有序 分区内有序 队列内有序
消息回溯 支持(基于 offset) 支持(基于 cursor) 支持(基于时间)
与 Flink 集成 原生,Exactly-Once 较成熟 一般
运维成熟度 极高,生态最完善 中等 中等

我个人习惯在实时特征平台里,Kafka 是消息层的首选。原因很简单:Flink 和 Kafka 的集成是最深的,从 checkpoint 到 exactly-once 语义,都是原生支持。

避坑指南:我曾经遇到过一个坑——Kafka 分区数设置不合理。分区太多导致文件句柄耗尽,分区太少导致消费能力不足。我的经验是:分区数 = max(生产者吞吐量 / 分区写入速度, 消费者并行度),一般建议 3 的倍数。

2.4 整体选型框架

这三者不是孤立的,它们需要协同工作。下面这张图展示了实时特征平台的核心技术栈关系:

实时特征平台核心技术栈 实时特征平台核心技术栈 数据源 消息队列 (Kafka) 实时计算 (Flink) 特征存储 (Redis) 特征存储 (HBase) 特征服务 数据流方向:数据源 → Kafka → Flink → Redis/HBase → 特征服务

2.5 选型总结

最后,我整理了一个快速决策表,方便你在实际项目中参考:

场景 推荐组合 理由
高并发低延迟(如推荐系统) Kafka + Flink + Redis 毫秒级延迟,高吞吐
大数据量稀疏特征(如广告系统) Kafka + Flink + HBase PB 级存储,列族灵活
批流一体(如数据中台) Kafka + Flink + Redis + HBase 热数据 Redis,冷数据 HBase
团队 Java 技术栈 Kafka + Flink + Redis Flink 原生 Java API
团队 Python 技术栈 Kafka + Spark + Redis PySpark 生态更成熟

最后说一句:选型不是一锤子买卖。我见过太多团队一开始选了“完美”的技术栈,结果业务变了,架构也得跟着变。保持灵活,留好扩展点,比选对技术更重要。