前几天,一个粉丝私信我,说他在面试时被 Redis 狠狠“教育”了一波。
面试官微微一笑:“Redis 里有 1 亿个 key,其中 10 万个以固定前缀开头,你怎么把它们找出来?”
他脱口而出一句 keys prefix* ,然后……就没有然后了。
这道题,真的只是考你会不会用命令吗?
故事开始:一座住着 1 亿人的城市
我们先不聊 Redis,先来讲个故事。
想象一下,有一座超级城市,里面住了 1 亿人。每个人都有姓名、身份证、门牌号,而他们的名字,就是 Redis 里的 key。这座城市的户籍系统,就是 Redis。
有一天,市长(面试官)突然问你:“小米啊,这座城市里,有 10 万个人,他们的姓都叫『张』,你怎么把这 10 万个人全部找出来?”
你想了想,拍着胸脯说:“简单!我翻一遍全城户口本,看到姓张的,全记下来!”
市长点点头:“嗯,说说你怎么翻?”
你说:“我用 KEYS 张*。”
恭喜你,第一问答对了。
第一反应:KEYS,简单粗暴
回到 Redis 世界。如果我们要找出某个固定前缀的 key,比如:
最直觉的方式就是:
示例代码
是不是很爽?
- 不用分页
- 不用游标
- 一条命令,全给你
就像翻户口本,一口气从第一页翻到最后一页。
面试官的“死亡追问”
这时候,面试官一般会身体前倾,语气放慢:“那如果这个 Redis,正在给线上的业务提供服务呢?”
你如果此时还在说:“那也用 KEYS 呗,很快的。”
那我只能说一句:兄弟,你已经站在事故复盘会上了。
关键点来了:Redis 的灵魂——单线程
这道题真正考的,不是命令,而是Redis 的核心特性。
Redis 是单线程的。
什么意思?我们再回到那座城市。这座城市的户籍系统只有一个窗口、一个工作人员。
平时:
- 查一个人
- 改一个地址
- 新增一条记录
- 都很快
但你现在要干什么?
- 翻 1 亿条记录
- 挨个看姓是不是“张”
那这个窗口会发生什么?所有人排队等着,窗口被你一个人占死。
KEYS 命令的真正问题
在 Redis 中,KEYS 有几个致命特点:
1、会遍历整个 keyspace
- 不管你只想要 10 万个
- Redis 都要把 1 亿个 key 全扫一遍
2、是同步执行的
- Redis 是单线程
- 执行 KEYS 时:
-
- 不能处理读请求
- 不能处理写请求
- 不能处理过期 key
- 不能处理心跳
3、线上表现:服务“假死”
你会看到:
- RT 飙升
- 接口超时
- 连接堆积
- 业务报警狂响
面试官想听到的关键词: “KEYS 会阻塞 Redis 主线程,导致线上服务停顿。”
表格总结:KEYS 的问题在哪里?
那怎么办?换个思路:不要“一口气翻完”
市长这时候又问你:“那有没有一种办法,不霸占窗口,一点点翻,翻完再走?”
你眼睛一亮:“有!我们可以分批翻!”
这,就是 SCAN。
SCAN:像翻书一样,慢慢来
SCAN 的设计思想就一句话:不要一次干完,分多次慢慢扫。
SCAN 的特点
- 每次只扫一小部分
- 不阻塞 Redis
- 用游标(cursor)记录进度
- 允许中途被打断
基本用法:
SCAN 示例:一步步找 key
返回结果大概是:
说明什么?
- "13976":下一个游标
- 后面是本次扫描到的部分 key
接着你继续:
一直扫,直到 cursor 变成 "0"。
SCAN 的“坑”:会有重复 key
这里是很多人容易翻车的地方。为什么会重复?
- Redis 在 scan 过程中
- key 可能发生:
-
- 扩容
- rehash
- 迁移
所以 Redis 不保证每个 key 只返回一次。
官方态度也很坦荡: “SCAN 可能返回重复元素,但不会漏。”
解决方案:客户端去重
既然 Redis 不帮你去重,那就我们自己来。
Java 示例代码(思路版)
关键点:
- 使用 Set 去重
- 不关心是否重复返回
- 最终结果是完整的
KEYS vs SCAN 对比总结
面试官想要的“标准答案”
如果你在面试中,这样回答,基本就稳了:
“可以使用 KEYS 指令匹配前缀,但它会阻塞 Redis 主线程。
因为 Redis 是单线程模型,KEYS 会遍历整个 keyspace,在线上环境可能导致服务不可用。
更安全的做法是使用 SCAN 指令分批扫描,虽然可能返回重复 key,但可以在客户端进行去重。”
这一段,建议你直接背下来。
总结:技术不是会用命令,而是懂后果
很多人学 Redis,停留在:“我知道这个命令怎么用。”
但面试官真正想考的是:“你敢不敢在生产环境用?”
KEYS 就像一把大锤:
- 小数据:很爽
- 大数据:砸死自己
而 SCAN,就像耐心和工程经验的结合体。
技术的成熟,不是更快,而是更稳。
END
如果你觉得这篇文章对你有帮助,欢迎点个**「在看」,也可以转给**那个总爱在生产上敲 **KEYS *** 的同事。
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!