Redis 数据结构选型:别把所有需求都塞进 String
Redis 快不代表任何建模都合理。数据结构决定命令复杂度、内存布局、并发原子性和后续扩展方式。选型时先写出核心访问模式,再判断是否需要排序、去重、范围查询、消费确认或近似统计。
String:缓存、计数和位操作
String 适合序列化对象、计数器、分布式状态标记和 Bitmap。写缓存时同时设置 TTL,避免忘记过期:
SET user:42 '{...}' EX 300
INCR article:42:view
不要把一个不断增长的大 JSON 当数据库使用。更新单个字段需要读改写整个对象,还会增加网络与复制开销。
Hash:字段级读写
用户配置、会话摘要等小对象适合 Hash:
HSET session:123 user_id 42 status active updated_at 1720000000
HGET session:123 status
Hash 的 TTL 主要作用在整个 Key 上。字段生命周期差异很大时,应拆分 Key 或使用支持字段过期的新能力前确认服务版本与兼容性。
Set 与 Sorted Set
Set 适合去重关系、共同成员和随机抽取:
SADD article:42:likers u1 u2
SISMEMBER article:42:likers u1
Sorted Set 为成员附带 Score,适合排行榜、延迟队列和时间线索引:
ZADD hot:articles 128 article:42
ZREVRANGE hot:articles 0 19 WITHSCORES
Score 是双精度浮点数,超大整数和复合排序键要注意精度。需要同分稳定排序时,可把时间或序号编码进成员或重新设计 Score。
List 与 Stream
List 适合简单队列和两端操作,但缺少消费者组、Pending 和确认机制。需要多个消费者、消息确认、重放和消费进度时,优先考虑 Stream:
XADD events:* * type article.published article_id 42
XREADGROUP GROUP notifier worker-1 COUNT 10 BLOCK 5000 STREAMS events:* >
XACK events:* notifier 1710000000000-0
Stream 仍需要长度治理,可使用近似裁剪,并监控 Pending。它不是 RabbitMQ 的完全替代,跨服务路由、复杂重试和成熟运维场景仍要评估专业消息队列。
Bitmap 与 HyperLogLog
Bitmap 适合按用户 ID 或日期记录二值状态,例如每日签到;HyperLogLog 用很小空间估算去重数量,适合 UV 趋势,但结果是近似值,不能用于计费或精确名单。
生产使用技巧
- 禁止在大库执行
KEYS *,使用SCAN分批遍历。 - Key 带业务前缀和版本,例如
wr:article:v1:42。 - 大集合分页读取,避免一次返回数十 MB。
- 使用 Lua 或事务保证跨多个命令的原子业务规则,但脚本应短小。
- 监控 Big Key、Hot Key、命中率、淘汰、延迟和复制积压。
- 缓存失效要有恢复策略,Redis 不能成为唯一事实来源。

评论
0 条讨论