redis 获取所有key(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在使用 Redis 进行开发时,我们常常需要快速获取数据库中的所有 Key,例如在调试、数据清理或统计分析场景中。然而,Redis 的 Key 获取并非简单的操作,不同的命令和方法会直接影响性能和系统稳定性。本文将从基础概念出发,结合实际案例,深入讲解如何高效安全地获取 Redis 中的所有 Key,并帮助开发者理解背后的设计逻辑。


一、Redis Key 获取的核心命令:KEYS 和 SCAN

1.1 KEYS 命令:直接获取所有 Key

命令语法KEYS pattern
KEYS 是 Redis 最基础的 Key 获取命令,它会返回所有匹配给定模式的 Key。例如:

redis> KEYS *  
1) "user:1001"  
2) "session:abc123"  
3) "cache:products"  

优点

  • 简单直接:一行命令即可获取所有 Key,适合测试或小型数据集。
  • 模式匹配:支持通配符(如 *?),可筛选特定格式的 Key。

缺点

  • 阻塞问题:当数据库中 Key 数量庞大时,KEYS 会阻塞 Redis 主线程,导致服务不可用。例如,一个包含 100 万 Key 的数据库,执行 KEYS * 可能需要数秒甚至更久,期间 Redis 无法处理其他请求。
  • 资源消耗大:返回大量数据时,内存和网络传输压力显著增加。

类比比喻
想象你在图书馆中寻找所有书名包含“Redis”的书籍,KEYS 就像直接搬空整个书架,虽然能快速找到目标,但会打乱其他读者的借阅流程。


1.2 SCAN 命令:分批遍历 Key

为解决 KEYS 的阻塞问题,Redis 2.8 引入了 迭代器模式SCAN 命令。它通过游标(Cursor)分批次返回 Key,避免一次性占用资源。

命令语法SCAN cursor [MATCH pattern] [COUNT count]

  • cursor:起始游标值(初始为 0),后续由 Redis 返回。
  • MATCH:可选参数,用于过滤 Key 模式。
  • COUNT:建议每次返回的 Key 数量(实际可能更多)。

示例代码

redis> SCAN 0 MATCH user:* COUNT 10  
1) "123"  
2) ["user:1001", "user:1002", "user:1003"]  
redis> SCAN 123 MATCH user:* COUNT 10  
1) "456"  
2) ["user:1004", "user:1005"]  
...  

优点

  • 低阻塞性:每次只处理少量 Key,主线程响应不受影响。
  • 兼容模式匹配:支持类似 KEYS 的模式过滤。

关键点

  • 游标需要循环使用,直到返回 0 表示遍历完成。
  • COUNT 是建议值而非固定值,实际返回数量可能因 Redis 内部策略而变化。

1.3 KEYS 和 SCAN 的性能对比

场景KEYSSCAN
小规模数据快速高效稍显冗余(需循环)
大规模数据高风险(阻塞服务)安全可靠
实时性要求可能导致服务中断平稳运行
资源消耗内存和带宽压力大渐进式消耗资源

类比比喻
KEYS 像是“一次性搬空仓库”,而 SCAN 则是“分批次搬运”,既保证效率又不打乱仓库日常运作。


二、实战场景与代码示例

2.1 场景一:调试时快速查看 Key

需求:在本地开发环境中,快速查看所有以 cache: 开头的 Key。

redis> KEYS cache:*  
1) "cache:users"  
2) "cache:products"  

注意事项

  • 本地测试环境 Key 数量少,KEYS 是安全的。
  • 生产环境避免直接使用 KEYS,改用 SCAN

2.2 场景二:清理过期 Key

需求:定期删除前缀为 temp: 且未设置过期时间的 Key。
实现思路

  1. 使用 SCAN 遍历所有 Key,过滤出符合条件的 Key。
  2. 对每个 Key 执行 DEL 命令。

Python 实现示例

import redis  

client = redis.Redis(host='localhost', port=6379)  

cursor = '0'  
while cursor != 0:  
    cursor, keys = client.scan(cursor=cursor, match='temp:*', count=100)  
    if keys:  
        client.delete(*keys)  

关键点

  • 通过 scan() 方法自动处理游标循环。
  • count 参数需根据业务调整,平衡遍历速度与资源消耗。

2.3 场景三:统计 Key 数量

需求:统计 Redis 中所有 Key 的总数。
方法

redis> DBSIZE  
(integer) 15000  

DBSIZE 可直接返回当前数据库的 Key 数量,但无法统计特定模式的 Key。若需统计特定前缀的 Key 数量,则需结合 SCAN

count = 0  
cursor = '0'  
while cursor != 0:  
    cursor, keys = client.scan(cursor=cursor, match='user:*')  
    count += len(keys)  
print(f"Total user keys: {count}")  

三、进阶技巧与注意事项

3.1 使用 COUNT 参数优化遍历速度

SCANCOUNT 参数控制每次返回的 Key 数量,默认值为 10。增大 COUNT 可加快遍历速度,但会增加单次请求的资源占用。例如:

redis> SCAN 0 MATCH * COUNT 1000  

建议

  • 小型数据集可设置 COUNT 1000
  • 大型数据集建议逐步调整,观察系统负载后再决定。

3.2 结合 MATCH 和 TYPE 过滤 Key

若需过滤特定类型的 Key(如仅获取字符串类型的 Key),可结合 SCANTYPE 命令:

cursor = '0'  
while cursor != 0:  
    cursor, keys = client.scan(cursor=cursor, match='user:*')  
    for key in keys:  
        if client.type(key) == b'string':  
            # 处理字符串类型 Key  
            pass  

3.3 注意游标的边界条件

在使用 SCAN 时,需确保循环终止条件正确。例如,在 Python 中:

cursor = '0'  
while cursor != '0':  # 注意游标是字符串类型  
    cursor, keys = client.scan(cursor=cursor, ...)  

若直接比较 cursor != 0(整数),可能导致无限循环。


四、替代方案与高级用法

4.1 使用 Lua 脚本优化批量操作

若需同时获取并处理 Key(如删除),可编写 Lua 脚本减少网络往返:

local cursor = tonumber(ARGV[1])  
local pattern = ARGV[2]  
local count = tonumber(ARGV[3])  

local result = redis.call('SCAN', cursor, 'MATCH', pattern, 'COUNT', count)  
local keys = result[2]  
redis.call('DEL', unpack(keys))  

return result  

在客户端调用:

script = """  
...  # 上述 Lua 脚本  
"""  
client.eval(script, 0, '0', 'temp:*', '100')  

4.2 Redis 集群环境的 Key 遍历

在 Redis 集群中,SCAN 只能遍历单个节点的 Key。若需全局遍历,需结合 CLUSTER NODES 获取所有节点并分别执行 SCAN


结论

Redis 的 Key 获取操作看似简单,实则需要开发者根据场景选择合适的方法。对于开发调试或小数据量场景,KEYS 是快速有效的工具;但在生产环境中,SCAN 的分批次迭代模式能显著提升系统稳定性。通过结合模式匹配、类型过滤和 Lua 脚本优化,开发者可以灵活应对各种复杂需求。掌握这些技巧不仅能提升代码效率,还能避免因操作不当导致的性能问题。

关键总结

  • 小数据KEYS 简单直接。
  • 大数据SCAN 安全高效,需循环处理游标。
  • 生产环境禁用 KEYS,优先使用迭代模式。

希望本文能帮助开发者在 Redis 开发中游刃有余地获取和管理 Key!

最新发布