3、特征存储设计:Redis、HBase、Cassandra 在实时特征中的存储模式与选型

实时特征计算出来之后,放哪儿?

这个问题,我当年刚做实时特征的时候,觉得很简单——不就是个缓存吗?Redis 一把梭。后来线上出了几次事故,我才意识到,特征存储的选型,直接决定了整个实时特征系统的可用性、成本和运维复杂度。

今天我们就来聊聊三种主流存储:Redis、HBase、Cassandra。它们各自适合什么场景?怎么用?坑在哪儿?

核心观点:没有银弹。特征存储选型取决于三个维度——QPS 高低、数据量大小、一致性要求。选对了,事半功倍;选错了,天天救火。

实时特征存储选型决策树 特征数据需要存储 QPS高 + 数据量小 QPS中 + 数据量大 QPS高 + 数据量大 Redis HBase Cassandra 选型要点: • Redis:毫秒级延迟,适合用户画像、实时计数等小数据量高频访问场景 • HBase:强一致性,适合需要事务保障、数据量大的离线+实时混合场景 • Cassandra:高可用、无单点,适合跨机房部署、写多读少的特征场景 • 我个人习惯:先看 QPS 和数据量,再看一致性要求,最后看运维能力 • 避坑:不要为了省事把所有特征塞进同一个存储,分场景设计才是正道

3.1 Redis:实时特征的"快枪手"

Redis 是我用得最多的特征存储。为什么?快。单机 QPS 能到 10 万+,延迟在毫秒级。对于实时推荐、实时广告这类场景,Redis 几乎是标配。

但 Redis 不是万能的。我见过很多团队把 Redis 当数据库用,结果内存爆了、数据丢了、主从切换卡了。说白了,Redis 是缓存,不是持久化存储。

Redis 在实时特征中的典型模式

  • Hash 结构:存储用户画像特征。key 是 user_id,field 是特征名,value 是特征值。适合批量读取。
  • Sorted Set:存储实时排行榜特征。比如商品热度分,用 score 排序。
  • String + 过期时间:存储临时特征,比如 session 级别的行为特征,TTL 设成 30 分钟。
  • Bitmap:存储用户是否点击、是否曝光等布尔特征,内存占用极小。
// 用户画像特征写入示例
// key: user:profile:{user_id}
// field: age, gender, city, ltv
// value: 对应的特征值

// 写入
HSET user:profile:10001 age 28 gender male city beijing ltv 3.5

// 批量读取
HMGET user:profile:10001 age gender city
// 返回: ["28", "male", "beijing"]

// 设置过期时间,防止僵尸数据
EXPIRE user:profile:10001 86400  // 24小时过期

我的经验:Redis 的过期策略一定要用好。我曾经在一个项目里没设过期时间,结果用户画像越积越多,内存从 8G 涨到 32G,最后 OOM 了。现在我的习惯是:所有特征数据都设 TTL,除非你明确知道它需要永久保留。

Redis 的坑

  • 内存有限:数据量超过内存容量,要么扩容,要么淘汰。我建议单机不超过 32G。
  • 持久化弱:RDB 和 AOF 都有丢数据的风险。别把 Redis 当唯一存储。
  • 大 key 问题:一个 Hash 里有几百万个 field,会导致阻塞。我踩过这个坑,后来用拆分 key 解决。

3.2 HBase:强一致性的"老大哥"

HBase 适合什么场景?数据量大、需要强一致性、对延迟要求不那么苛刻的场景。

我记得有一次做风控特征存储,要求特征数据必须严格一致——用户的行为一旦写入,必须立刻能被读到,不能有延迟。Redis 的主从异步复制满足不了,最后选了 HBase。

HBase 在实时特征中的存储模式

  • Rowkey 设计:通常是 user_id + 时间戳的反转,保证热点分散。
  • 列族设计:按特征类型分列族,比如 cf_action(行为特征)、cf_profile(画像特征)。
  • 版本控制:HBase 天然支持多版本,适合存储特征的历史变化。
// HBase 特征存储 Rowkey 设计
// Rowkey: user_id(4字节) + reverse_timestamp(8字节)
// 例如: 10001_18446744073709551615

// 写入特征
put 'feature:user', '10001_18446744073709551615', 'cf_action:click_cnt', '15'
put 'feature:user', '10001_18446744073709551615', 'cf_action:view_cnt', '32'

// 读取最新特征
get 'feature:user', '10001_18446744073709551615'

// 扫描某个时间范围的特征
scan 'feature:user', {STARTROW => '10001_18446744073709550000', 
                      STOPROW => '10001_18446744073709551615'}

注意:HBase 的 Rowkey 设计是重中之重。设计不好,就会出现 Region 热点——所有请求打到一个 Region Server 上。我见过一个团队把时间戳放 Rowkey 前缀,结果每天凌晨写入量暴增,Region Server 直接挂掉。Rowkey 一定要加盐(salting)。

HBase 的适用场景

  • 风控特征:需要强一致性,不能容忍数据不一致。
  • 离线+实时混合:HBase 可以同时支撑批量导入和实时写入。
  • 特征历史回溯:多版本特性方便做特征回滚和调试。

3.3 Cassandra:高可用的"分布式战士"

Cassandra 是我后来才深入使用的。说实话,一开始我对它有点偏见——觉得它太复杂。但后来做跨机房部署的特征存储时,Cassandra 的优势就体现出来了。

Cassandra 没有单点故障,支持多数据中心复制,写入性能极好。适合写多读少、对可用性要求极高的场景。

Cassandra 在实时特征中的存储模式

  • Primary Key 设计:Partition Key 决定数据分布,Clustering Key 决定排序。
  • TTL 自动过期:Cassandra 支持表级别和列级别的 TTL,非常适合临时特征。
  • 轻量级事务:通过 IF NOT EXISTS 实现去重写入。
// Cassandra 建表语句
CREATE TABLE feature.user_features (
    user_id text,
    feature_name text,
    feature_value text,
    update_time timestamp,
    PRIMARY KEY (user_id, feature_name)
) WITH default_time_to_live = 86400;  // 24小时自动过期

// 写入特征
INSERT INTO feature.user_features (user_id, feature_name, feature_value, update_time)
VALUES ('10001', 'click_cnt_1h', '15', toTimestamp(now()));

// 读取某个用户的所有特征
SELECT * FROM feature.user_features WHERE user_id = '10001';

// 读取特定特征
SELECT feature_value FROM feature.user_features 
WHERE user_id = '10001' AND feature_name = 'click_cnt_1h';

我的建议:Cassandra 的 TTL 机制非常实用。实时特征很多都是有时效性的——比如"过去1小时点击次数",过了1小时就没意义了。用 TTL 自动清理,省去了写定时任务的麻烦。

Cassandra 的坑

  • 读性能不如写性能:Cassandra 是写优化的,读路径比较重。如果读 QPS 很高,需要加缓存层。
  • 二级索引性能差:别在 Cassandra 里做复杂查询,它只适合按主键查询。
  • 数据模型设计要一次到位:Cassandra 不支持表结构变更,设计错了就得重建表。

3.4 选型对比:一张表说清楚

维度 Redis HBase Cassandra
延迟 毫秒级(1-5ms) 10-50ms 5-20ms
QPS 10万+ 1-5万 5-10万
数据量 GB ~ 几十GB TB ~ PB TB ~ PB
一致性 最终一致性 强一致性 可调一致性
持久化 弱(RDB/AOF) 强(HDFS) 强(SSTable)
运维复杂度 低 高 中
典型场景 用户画像、实时计数 风控特征、离线+实时混合 跨机房、写多读少

3.5 我的选型建议

说了这么多,到底怎么选?我总结了一个简单的判断逻辑:

  1. 先看数据量:如果数据量在几十 GB 以内,无脑选 Redis。简单、快、好维护。
  2. 再看一致性要求:如果必须强一致,选 HBase。别用 Redis 做强一致场景,你会后悔的。
  3. 最后看可用性要求:如果要求 99.99% 可用,选 Cassandra。它的去中心化架构天生高可用。

一个真实案例:我之前做的一个实时推荐系统,用户画像特征用 Redis(数据量 20GB,QPS 8万),行为序列特征用 HBase(数据量 2TB,需要强一致),跨机房同步的特征用 Cassandra(多数据中心复制)。三种存储各司其职,系统跑了两年没出过大问题。

嗯,特征存储设计就聊到这儿。记住一句话:没有最好的存储,只有最合适的存储。根据你的场景选,别跟风。