
从「背场景」到「做决策」:Redis 选型决策树
每次有人问我"Redis 能做什么",我都想反问一句——你是在问它能做什么,还是在问你该让它做什么?
这两个问题差了一整个段位。
打开任何一篇 Redis 使用场景文章,你会看到相似的清单:缓存、分布式锁、排行榜、消息队列、限流器、布隆过滤器……11 种,15 种,甚至有人凑出 16 种。背下来不难。面试时像报菜名一样说出来也不难。
难的是什么?
面对一个具体业务需求,你怎么在 3 分钟内判断"该不该让 Redis 做这件事"?
背 11 种场景是记忆力。给定需求,快速判断用不用 Redis、用哪种数据结构、什么时候该撤退——这才是决策力。后者在面试中更有区分度。
我见过太多开发者掉进一个陷阱:因为"Redis 能做 X"就让 Redis 做了 X,然后在生产环境踩坑。能做和该做之间,隔着一道判断题。
这篇文章给你一棵决策树。沿着 3 个问题往下走,每个场景的答案会自己浮出来。不用背,用推导。
1 决策树全貌:3 个问题定生死
先给结论。决策 Redis 是否适合某个场景,你只需要回答 3 个问题:
- 读写比如何?(读多写少 / 写多读少 / 均衡)
- 一致性要求到什么级别?(最终一致 / 强一致 / 事务级)
- 数据量级和内存的关系?(热数据 < 内存 / 热数据 > 内存 / 全量远超内存)
为什么偏偏是这 3 个?不是 4 个,不是 5 个?
因为它们直接对应 Redis 的 3 个核心架构特征:
- 内存存储 → 容量有天花板,数据量级是硬约束
- 单线程命令执行 → 原子性天然强,但一条慢命令阻塞全局
- 丰富数据结构 → 不同结构匹配不同读写模式,选错结构等于自废武功
其他维度当然也重要,但它们是二级问题。先用上面 3 个问题定方向,再用以下清单细化:
- 延迟 SLA:P99 要求 < 1ms?需要评估网络拓扑和持久化策略对延迟的影响
- 运维复杂度:团队有没有 Redis Cluster / Sentinel 的运维经验?
- 内存成本:云环境 Redis 内存 GB 单价远高于磁盘存储,中小团队要算账
- 持久化需求:RDB fork 在大数据集(>10GB)上可阻塞数百毫秒,AOF rewrite 同理
3 个问题定方向,4 个维度做细化。先过了主线再走支线。

抽象看不够直观。走几个真实场景试试。
走树演示:3 个场景
场景 A:电商秒杀库存扣减
- 读写比?→ 高并发写(瞬时数万请求同时扣减)
- 一致性?→ 强一致(超卖不可接受,一件都不能多)
- 量级?→ SKU 级别,万级热门商品
决策路径走到了"Redis 原子操作 + 额外保障"。具体方案:用 Lua 脚本做原子"检查库存 > 0 再扣减"。注意,单纯 DECR 只是原子递减,不检查下界,库存可以减到负数,不能防超卖。Redis 在这个场景是最优解:纯内存操作,微秒级响应,单线程天然避免竞争。
但有退出条件:如果扣减需要跨多个服务(比如同时扣库存 + 扣优惠券 + 扣积分),单靠 Redis 的原子性不够,需要分布式事务方案(如 TCC)兜底。
场景 B:社交 Feed 流排序
- 读写比?→ 读远多于写(用户发帖少,刷 Feed 极频繁)
- 一致性?→ 最终一致(晚 3 秒看到新动态完全可接受)
- 量级?→ 单用户 Feed 百级条目,但用户量千万级
走到"Redis 缓存-经典场景"。用 ZSET 按时间戳排序,每个用户一个 ZSET 存 Feed ID 列表。读取用 ZREVRANGE 取最新 N 条,O(log N + K) 响应。
退出条件:如果 Feed 需要个性化推荐算法介入(不是简单的时间排序),Redis 只能做缓存层,排序逻辑必须在应用层或推荐引擎中完成。
场景 C:订单状态机
- 读写比?→ 均衡(状态流转频繁,查询也频繁)
- 一致性?→ 事务级(订单从"待支付"变"已支付"不能出错,不能丢)
- 量级?→ 日百万订单
走到了"不推荐 Redis 做主存储"。订单状态机需要的是:持久化保证 + 事务性状态流转 + 审计日志。这些都不是 Redis 的强项。
正确方案:MySQL/PostgreSQL 做订单主存储(InnoDB 行锁保证状态流转原子性),Redis 做热订单的查询加速缓存。各司其职。

3 个场景,每个 30 秒内有答案。这就是决策树的价值,不用背,用推。
2 缓存——Redis 的甜蜜区
缓存是 Redis 的主场。绝大多数 Redis 实例都在做缓存相关的工作(据 Redis Labs 历年调查,缓存是排名第一的用途)。
但我想说的不是"Redis 能做缓存"这种废话。我想说的是:缓存场景里,Redis 的甜蜜区到底在哪?你的用法在不在甜蜜区里?
答案藏在数据结构的底层编码方式中。

编码决定效率
Redis String 有两种内部编码:
- embstr(value ≤ 44 字节):Redis 对象头(16 字节)和 SDS 字符串体在同一块连续内存中。一次 malloc,零碎片,CPU cache 友好。
- raw SDS(value > 44 字节):对象头和字符串体分开分配。两次 malloc,有内存碎片风险,且访问需要多一次指针跳转。
这意味着一个被大多数人忽略的设计原则:如果你的缓存 value 能控制在 44 字节以内,内存效率最高。
什么东西适合?session token(通常 32-40 字符)、UUID(36 字符)、短数字 ID、布尔标记、小计数器。这些是 String 缓存的绝对甜蜜区。
Hash 也有类似的分水岭。Redis 7.x 中,field 数量 ≤ 128(hash-max-listpack-entries 默认值)且每个 field 值 ≤ 64 字节时,使用 listpack 编码(紧凑的线性字节数组,取代了旧版的 ziplist)。一旦超过任一阈值,自动升级为 hashtable。
差距有多大?listpack 的内存效率比 hashtable 高出约 3-5 倍(100 field 场景)。同样存 100 个用户属性字段,listpack 编码可能只占几 KB,hashtable 编码占用要翻几番。
这个阈值很多教程都写错——旧版 ziplist 时代默认确实是 512,Redis 7.x 换成 listpack 后改成了 128。别踩这个坑。listpack 是线性结构,查找是 O(N)。field 越多,HGET 越慢。实践中建议将单个 Hash 控制在 100 field 以内——既在默认阈值安全线内享受 listpack 的内存优势,又不让查找成为瓶颈。
设计原则:用户 profile 拆成多个小 Hash(每个控制在 100 field 以内),比塞进一个 500 field 的巨型 Hash 省内存也更快。
ZSET 同理:元素 ≤ 128 时用 listpack(紧凑但查找 O(N)),超过后升级为 skiplist + hashtable(O(log N) 但内存消耗翻 2-3 倍)。排行榜设计的第一步是预估你的最大元素量——这决定了底层编码,进而决定了内存成本和查询模式。
缓存模式的选择
Cache-Aside(旁路缓存)是最常见的模式。但它有一个天然弱点:读取 miss 后写入缓存,到下次更新 DB 前,缓存数据可能已过期。
三种缓存模式的适用条件:
| 模式 | 一致性 | 适用场景 | Redis 角色 |
|---|---|---|---|
| Cache-Aside | 最终一致 | 读多写少,容忍秒级延迟 | 旁路加速 |
| Write-Through | 高一致 | 读写均衡,不容忍脏读 | 同步写入 |
| Write-Behind | 弱一致 | 写极多,容忍数据丢失 | 写缓冲 |
注:Write-Through 和 Write-Behind 在 Redis 中无原生支持,需要应用层代码实现同步/异步写入逻辑。Write-Through 的"高一致"也非严格线性一致——并发写入时仍存在一致性窗口。

大部分业务场景用 Cache-Aside 就够了。如果你发现自己在实现 Write-Through 的复杂逻辑——停下来想想,是不是场景本身就不适合缓存。
缓存的退出条件
什么时候 Redis 缓存不该用?两个核心信号:
- 热数据集远超可用内存,或数据更新极其频繁且无规律:经验上,缓存命中率低于 85-90% 时(具体阈值因业务而异),缓存带来的收益会被 miss 后回源 DB 的开销抵消。监控你的 keyspace_hits / (keyspace_hits + keyspace_misses)。如果 TTL 设 10 秒,数据 3 秒就变了,缓存命中那 3 秒拿到的是脏数据,其余 7 秒是 miss,这种场景缓存是负优化。
- 一致性要求到了"不允许任何脏读"的级别:Cache-Aside 模式天然有窗口期(DB 更新后缓存失效前的那个瞬间)。如果这个窗口不可接受,别硬上缓存,改架构。
满足任意一个,重新评估方案。不是 Redis 不行,是场景不对。
3 分布式锁——边界在哪
分布式锁用 Redis?可以。但先问清楚边界在哪。
大部分教程告诉你 SET key value NX EX 30 就完事了。在单 Redis 实例、并发不高、允许偶尔失败的场景里,确实够用。Redisson 框架把这件事封装得更好——加上了看门狗续期、可重入支持、公平锁等特性。
问题不在于"怎么加锁"。问题在于:你的"分布式锁"到底需要多强的互斥保证?
脑裂场景:锁为什么会失效
Redis 主从复制是异步的。这一句话背后藏着一个致命的边界条件。
构造一个时序,你就明白问题有多真实:
T0 客户端A → Master: SET lock:order NX EX 30 → 成功,获得锁
T1 Master 宕机(锁数据尚未同步到 Replica)
T2 Sentinel 检测到 Master 不可达,开始 failover(通常需要数秒)
T3 Replica 被提升为新 Master(但它没有 lock:order 这个 key!)
T4 客户端B → 新Master: SET lock:order NX EX 30 → 成功,也获得了锁
T5 💥 客户端A 和 客户端B 同时持有锁 → 互斥性被打破

从 T0 到 T5,可能只有 3-5 秒。但这几秒足以让两个客户端同时操作同一份资源。
你可能想说:这个概率很低。没错,低——但"概率低"不等于"可以无视"。如果锁保护的是支付扣款操作,一次失效就是一笔资金损失,一个 P0 级事故。
Redisson 的看门狗能解决这个问题吗?不能。看门狗解决的是"锁过期但业务没执行完"的问题,解决不了"Master 宕机数据丢失"的问题。这是两个完全不同层面的风险。
Redlock:复杂度陷阱
Redis 作者 antirez 为了解决上述问题,提出了 Redlock 算法:向 N(推荐 5)个完全独立的 Redis 实例同时申请锁,获得多数派(≥ N/2 + 1 = 3)响应且总耗时未超过锁的有效期,才视为加锁成功。
听起来合理。但 Martin Kleppmann 在 2016 年那篇经典文章("How to do distributed locking")里提出了尖锐批评:Redlock 依赖节点时钟大致同步,但时钟跳变(NTP 校准、VM 迁移)会让过期计算不可靠;客户端拿到锁后遭遇 GC pause 或网络分区,锁可能早已过期但客户端不知道。更根本的问题是——Redis 不是共识系统,让它承担互斥保证,是用错误的工具解决问题。
我认为 Kleppmann 的分析在理论层面是对的。不过 antirez 在回应文章"Is Redlock safe?“中反驳:Redlock 不要求绝对时钟同步,只要时钟漂移远小于 TTL 就够了(现代硬件通常满足);GC pause 导致锁过期是所有分布式锁的通病,不是 Redlock 特有的问题。
两边都有道理。但工程实践中,判断不能只看理论——还要看成本。
我的决策建议是这样的:
- 90% 的场景:单 Redis 实例锁 + 合理过期时间(业务执行时间的 3 倍以上) + 业务层幂等设计 = 足够安全。脑裂是极低概率事件,用业务补偿兜底。
- 锁失效会造成资金损失:etcd 或 ZooKeeper。它们基于 Raft/ZAB 共识算法,互斥保证是协议级别的。但注意:etcd/ZK 写入吞吐通常在千级 QPS,获锁并发量极高(万级/秒)时需要应用层排队或分段锁。
- Redlock:要维护 5 个独立 Redis 实例,运维成本不低,但安全性提升有限(Kleppmann 的批评仍然成立)。性价比很差,不推荐作为首选。
一句话决策:锁失效会造成不可逆损失(资金/数据)?会 → etcd/ZK。不会 → Redis 单实例 + 幂等补偿。 Redlock 是一个复杂度陷阱——花了 5 倍的运维成本,买了一个"好一点但仍然不完美"的保证。

分布式锁考验的是一致性边界。接下来换个维度——看数据结构选择怎么影响性能天花板。
4 排行榜/计数器——选对结构
ZSET 天生就是排行榜的数据结构。O(log N) 插入,O(log N + M) 范围查询(M 为返回元素数),O(log N) 查排名。看起来无可挑剔。
但"用 ZSET 做排行榜"不是一句话就能搞定的事。数据量从 1 万到 1000 万,最优方案完全不同。拍脑袋选了方案 A,等数据量涨到百万级才发现扛不住——代价是重构。
ZSET 底层:skiplist 的代价
先搞清楚 ZSET 的底层。当元素超过 128 个(或单元素超过 64 字节),ZSET 从 listpack 升级为 skiplist + hashtable 双结构。
skiplist 的查找是 O(log N)——这是期望值。Redis 的 skiplist 提升概率 p=0.25,搜索深度按 log₄(N) 计算。N = 1 万时,平均约 7 层。N = 1000 万时,平均约 12 层。每多一层就是一次内存随机访问(pointer chase),CPU cache miss 率随之上升。
7 层和 12 层,看起来差距不大对吧?但乘以每秒数万次操作,这 5 层的差距就是 QPS 天花板的分水岭。
三方案性能推演
⚠️ 以下推演基于 Redis 时间复杂度和官方 benchmark 数据(redis-benchmark 单实例 ~10 万 QPS 基线),非同环境直接对比实测

方案 A:单 ZSET 全量存储
最简单直接的方案。一个 ZSET 装所有参与者的分数。
- 更新分数:ZADD key score member → O(log N)
- 查 Top-100:ZREVRANGE key 0 99 WITHSCORES → O(log N + 100)
- 查某人排名:ZREVRANK key member → O(log N)
N = 1 万时,每次操作约 7 跳,单实例轻松达到十万级 QPS。N = 100 万时,约 10 跳,QPS 仍在万级以上。N = 1000 万时,约 12 跳加上内存压力(单个 ZSET 占内存可达 GB 级),QPS 进一步下降但仍可用。
能用吗?当然能。但数据量从万级到千万级,性能衰减是肉眼可见的。千万级 ZSET 还有 Big Key 风险:DEL 可能阻塞主线程数秒(Redis 4.0+ 推荐用 UNLINK 异步删除),Cluster 迁移容易超时。
方案 B:分桶 ZSET(按分数段或时间段分片)
核心思路:把一个大 ZSET 拆成多个小 ZSET。
比如按分数区间:score 0-999 放 rank:bucket:0,score 1000-1999 放 rank:bucket:1。每个桶的 N 小,skiplist 层数少,单桶操作更快。
但代价是:
- 查 Top-K 可能需要跨桶合并(从最高分桶开始取,不够再取次高桶)
- 实现复杂度显著上升
- 查某人全局排名需要计算低分桶的总人数作为偏移
适合的场景:写入 QPS 极高(万级以上且持续增长)、分数分布相对均匀、可以接受实现复杂度的团队。
方案 C:ZSET + Hash 缓存热数据
ZSET 仍然存完整排行,但将 Top-100(或 Top-1000)用一个 Hash 单独缓存。定时任务(比如每 5 秒)从 ZSET 取最新 Top-K 写入 Hash。
读 Top-100 变成 HGETALL → O(K)(K=100,不随排行榜总规模增长)。写入仍然打到 ZSET(O(log N)),但高频的"查看排行榜"请求被 Hash 挡住了,不再重复扫 skiplist。
代价:排行榜有最多 5 秒的数据延迟。对于游戏排行、内容热度榜——完全可接受。对于实时竞拍——不行。
方案选择决策
| 数据量 | 写入压力 | 推荐方案 | 核心理由 |
|---|---|---|---|
| 万级 | 低 | 方案 A | 简单即正义,ZADD + ZREVRANGE 性能绰绰有余 |
| 十万-百万级 | 中等 | 方案 C | 读写解耦,查询不受 N 增长影响 |
| 百万级以上 | 高 | 方案 B | 分桶分压,每个桶维持高效操作 |
| 千万级以上 | 任意 | Redis Cluster 分片 + B/C 组合 | 单实例内存和 CPU 都扛不住。注意:Cluster 模式下分桶 ZSET 需用 hash tag {rank}:bucket:N 保证同 slot 操作 |
10 万以下闭眼方案 A。10 万以上先试方案 C,最小改动最大收益。百万级数据量才需要动分桶的心思。
排行榜和计数器的决策核心是数据结构选型。下一个场景换个赛道——消息队列,这里要决策的不是"用什么结构”,而是"用不用 Redis"。
5 消息队列——进退线
Redis Stream 在 5.0 引入,到 7.x 已经相当成熟。消费者组(Consumer Group)、消息确认(XACK)、消息持久化(AOF)、消费进度追踪——该有的功能都有了。
但"能当消息队列用"和"该当消息队列用"是完全不同的两个命题。
我的判断是:Redis Stream 是一个优秀的"轻量级异步解耦"工具,但它不是、也不该是你的"企业级消息中间件"。
Redis Stream vs Kafka:维度拆解
⚠️ 以下对比基于官方文档和公开 benchmark 推演,非同环境直接对比实测

吞吐量差距:Redis Stream 单实例约 10-15 万 msg/s(消息体 < 1KB)。Kafka 单 broker 可达约 100 万 msg/s。差一个数量级。Redis 是纯内存操作所以延迟低,但吞吐上限受单线程模型限制。
持久化保证:Redis Stream 的持久化依赖 AOF(append-only file)。如果用 everysec 策略,极端宕机可能丢 1 秒数据。如果用 always 策略,性能打折。Kafka 的分区副本机制(acks=all + ISR)提供的持久化保证强得多——Leader 写入后等待所有 ISR 副本确认。
消息堆积容忍度:Redis Stream 的数据全在内存。堆积 100 万条小消息就要占几百 MB 内存。通常用 MAXLEN 或 MINID 做截断。Kafka 是磁盘顺序写,百 GB 甚至 TB 级堆积都是正常操作。
运维成本:Redis Stream 零额外部署——你已有的 Redis 集群就能承载。Kafka 需要独立集群:以前是 ZooKeeper + broker,现在 KRaft 模式好一些,但仍需要独立运维。对于小团队,这不是小事。
消费语义:Redis Stream 的 XREADGROUP + XACK 机制实现了 at-least-once 语义。但如果消费者崩溃后没有 XACK,消息会留在 pending 列表里等待认领(XCLAIM)。这个机制能用,但没有 Kafka Consumer Group 的 rebalance 那么成熟和自动化。
场景分界线
用 Redis Stream 的信号:
- 日消息量在十万级以下
- 消息体小(< 1KB,典型的事件通知类)
- 允许极端场景丢少量尾部消息
- 团队已有 Redis 运维经验,不想为了一个异步需求引入 Kafka 全家桶
- 需求本质是"轻量级解耦"——A 服务通知 B 服务做某件事
切换到 Kafka 的信号:
- 日消息量十万级以上
- 消息不能丢(金融级可靠性要求)
- 需要 TB 级堆积能力和任意时间点消息回溯
- 多个消费者组需要独立消费同一份数据流
- 已有 Kafka 集群和运维团队
灰色地带(日十万到百万之间):取决于你的团队。有 Kafka 经验就直接上 Kafka,省得以后迁移。没有的话,Redis Stream 先扛着,监控好内存和堆积量,什么时候扛不住再迁移。迁移成本不高,因为 Stream 和 Kafka 的消费模型很接近。
一句话决策:日消息量十万级以下、允许极端场景丢数据 → Redis Stream。超过这个线 → Kafka。 先用 Stream 扛着,扛不住再迁 Kafka,迁移成本不高。
6 冷门场景:快速决策
有些 Redis 场景不需要一整章来展开。但面试时经常被问到。给你每个场景的快速决策结论和边界条件。

布隆过滤器
用它的唯一正当理由:你需要快速回答"这个元素一定不在集合中"。
注意"一定不在"这个措辞。布隆过滤器说"不在",那就真不在。说"在",有一定概率是误判(false positive)。它解决的是"确定性否定"问题。
典型场景:缓存穿透防护(拦截不存在的 key 请求)、爬虫 URL 去重、推荐系统已曝光过滤。
内存开销多大?基于 BloomFilter 最优参数公式(m = -(n × ln p) / (ln 2)²)推算:
| 预期元素数 | 误判率 1% 内存 | 误判率 0.1% 内存 | 最优哈希函数数 |
|---|---|---|---|
| 100 万 | ~1.14 MB | ~1.71 MB | 7 / 10 |
| 1000 万 | ~11.4 MB | ~17.1 MB | 7 / 10 |
| 1 亿 | ~114 MB | ~171 MB | 7 / 10 |
千万级以下,Redis BF 模块(RedisBloom)一条 BF.ADD 命令搞定,内存开销极低(十几 MB)。不用自己实现哈希函数,不用自己管理位数组。
不用 Redis 布隆过滤器的信号:
- 需要精确判断"在/不在"(布隆有误判,不适合)
- 需要删除元素(标准布隆不支持删除,Cuckoo Filter 可以但换了个数据结构)
- 元素量超过亿级且内存敏感(占用 100MB+ 的 Redis 内存,要权衡是否划算)
延时队列
Redis 实现延时队列的经典姿势:ZSET 中 score 设为消息到期的时间戳(Unix timestamp),消费者轮询 ZRANGE key min max BYSCORE(Redis 6.2+ 推荐语法,旧版用 ZRANGEBYSCORE)取出到期消息,然后 ZREM 删除。
为什么用 ZSET?因为 score 排序天然就是时间排序,按当前时间过滤就是取"已到期的所有任务"。O(log N + M) 的时间复杂度,M 是到期任务数。
本质上这是一个"穷人版"延时队列。功能够用、部署简单、不引入新依赖。适合日任务量不大(十万级以下)、精度要求秒级、不需要严格 exactly-once 语义的场景。ZRANGE…BYSCORE + ZREM 不是原子操作,需要 Lua 脚本或分布式锁配合。
什么时候该换?任务量到了百万级(轮询压力大,ZSET 内存膨胀),或者需要毫秒级精度,或者需要严格消息不丢。这时候 RocketMQ(原生延时消息)或 XXL-JOB 是更合适的选择。够用就用,扛不住再换,迁移成本很低。
社交关系(共同好友/关注列表)
Set 的交集运算 SINTER 看起来天然适合"共同好友"。两个用户各一个 Set 存关注列表,SINTER 取交集,完事。
用 Redis Set 的条件:
- 用户总量 < 百万
- 单用户关注/好友列表 < 5000 人
- 查询不频繁(非每次打开页面都算共同好友)
这个量级下,SINTER 操作耗时在毫秒级以内。内存占用需要留出余量——100 万用户 × 平均 500 关系 × 每个 member 实际占用约 60-70 字节(含 dictEntry、SDS header、内存对齐等 Redis 元数据开销)≈ 30-35 GB。一台大内存 Redis 能扛,但要做好容量规划。
不用 Redis Set 的信号:
- 用户量千万级以上 → 内存装不下(千万用户 × 1000 关系 = 百亿 member)
- 单用户关系数超万 → SINTER 两个万级 Set 的耗时会到达几十毫秒,阻塞单线程
- 需要多跳关系查询(好友的好友)→ Set 只能做一跳交集,多跳需要图计算
大规模社交图谱该用图数据库(Neo4j、TigerGraph)做离线分析,或者用 Spark/Flink 预计算共同好友列表存入缓存。Redis 只适合做"热点用户"的关系缓存——微博大 V 的粉丝列表 Top-N,而不是全量关系图。如果用 Redis Cluster,注意 SINTER 要求 key 在同一 slot,需用 hash tag(如 {user}:friends)保证。
决策速查表
回到最开头的问题:Redis 能做什么?
答案是它能做很多事。但你该让它做什么,取决于你的 3 个业务约束条件。

| 场景 | 推荐数据结构 | 推荐度 | 退出条件(触发任一则重新评估) |
|---|---|---|---|
| 缓存 | String / Hash | 强推 | 热数据远超内存 / 不容忍任何脏读 |
| 分布式锁 | String + NX | 推荐 | 锁失效会造成资金损失 |
| 排行榜 | ZSET | 强推 | 数据量千万级以上且写入压力极高 |
| 计数器/限流 | String INCR | 强推 | 需要跨实例全局精确计数 |
| 消息队列 | Stream | 条件推荐 | 日消息量十万级以上 / 消息不能丢 |
| 延时队列 | ZSET | 条件推荐 | 任务量大 / 需要毫秒级精度 |
| 布隆过滤器 | BF 模块 | 推荐 | 需要精确判断 / 需要删除元素 |
| 社交关系 | Set | 条件推荐 | 用户量千万以上 / 需要多跳查询 |
| 会话存储 | Hash | 推荐 | 会话数据需要复杂查询或联表 |
面试时怎么用这棵树
面试官问"Redis 有哪些使用场景"时,不要报菜名。
“缓存、分布式锁、排行榜、消息队列……” 这种回答和百度第一页搜索结果没区别。面试官听了几百遍了。
试试这样回答:
“我不会去背 Redis 有几种用法。在做场景选型时,我会从 3 个维度判断:读写比、一致性要求、数据量级。
举个例子——缓存场景,读多写少 + 最终一致 + 热数据可控,这是 Redis 的绝对甜蜜区,闭眼用。
但分布式锁就不一样了。如果涉及资金安全,我不会用 Redis——因为主从异步复制在 failover 时有锁失效风险。这种场景我会建议 etcd。
Redis Stream 做消息队列也是。日十万级以下、允许极端情况丢消息——可以。超过这个线就该上 Kafka。
关键是知道每种用法的边界在哪、什么时候该退出。”
这段回答包含了决策框架、具体判断、边界认知和替代方案。
比罗列场景更有说服力。
最后一句
Redis 强在特定约束条件下,它是那个最优解。
你的工作是判断:在你的具体场景里,它到底是不是最优解。如果不是,果断换。
决策能力 > 记忆力。这是这篇文章想说的全部。
原文发布于 止语Lab