• [问题求助] Redis中的hash和Java中的HashMap有啥区别
    Redis中的hash和Java中的HashMap有啥区别
  • [问题求助] Redis的ZipList、SkipList和ListPack之间有什么区别?
    Redis的ZipList、SkipList和ListPack之间有什么区别?
  • [问题求助] Redis中的ListPack是如何解决级联更新问题的?
    Redis中的ListPack是如何解决级联更新问题的?
  • [问题求助] ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?
    ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?
  • [问题求助] Redis中的setnx和setex有啥区别?
    Redis中的setnx和setex有啥区别?
  • [问题求助] Redis8.0的新特性有哪些?
    Redis8.0的新特性有哪些?
  • [问题求助] Redis中hash结构比string的好处有哪些?
    Redis中hash结构比string的好处有哪些?
  • [问题求助] Redis事务和MySQL事务的区别?
    Redis事务和MySQL事务有什么区别?
  • [问题求助] Redis能完全保证数据不丢失吗?
    Redis能完全保证数据不丢失吗?
  • [问题求助] RDB和AOF的写回策略分别是什么?
    RDB和AOF的写回策略分别是什么?
  • [问题求助] Redisson如何保证解锁的线程一定是加锁的线程?
    Redisson如何保证解锁的线程一定是加锁的线程?也就是如何有效的避免A线程加的锁被B线程解锁?
  • 几招搞定Redis如何高效安全的遍历所有key
    在 Redis 中,高效且安全地遍历所有 key 是一个需要谨慎处理的任务,因为如果操作不当,可能会对 Redis 的性能产生显著影响,尤其是在 key 数量非常庞大的情况下。一、使用 KEYS命令(​​不推荐在生产环境使用​​)命令: KEYS * 说明:KEYS命令会返回匹配指定模式(如 *表示所有 key)的所有 key。​​问题​​:KEYS是 ​​阻塞式操作​​,如果你的 Redis 数据量很大(比如百万级以上的 key),这个命令会一次性将所有 key 加载到内存并返回,这会导致 Redis 长时间阻塞,无法处理其他请求,从而影响线上服务的可用性。结论:❌ ​​严禁在生产环境中使用 KEYS *,尤其是在数据量大的情况下。​​二、使用 SCAN命令(​​推荐方式​​)命令: SCAN cursor [MATCH pattern] [COUNT count] 说明:SCAN是一个 ​​非阻塞的、基于游标的迭代器​​,用于渐进式地遍历 Redis 中的 key。它每次调用返回一小部分 key 和一个新的游标(cursor),你通过不断迭代调用 SCAN,直到游标返回 0,表示遍历完成。相比 KEYS,SCAN对 Redis 性能影响极小,适合生产环境使用。参数:cursor:游标,初始为 0,结束时也为 0。MATCH pattern(可选):匹配特定模式的 key,如 MATCH user:*。COUNT count(可选):建议每次返回的 key 数量,只是一个提示,不保证精确,一般可设为 100~1000。示例(伪代码 / redis-cli): # 第一次调用,cursor 从 0 开始 127.0.0.1:6379> SCAN 0 MATCH * COUNT 100 1) "17" # 下一次迭代的游标 2) 1) "key1" 2) "key2" ... (最多 COUNT 个 key) # 第二次用返回的游标继续 127.0.0.1:6379> SCAN 17 MATCH * COUNT 100 1) "0" # 游标为 0 表示遍历结束 2) 1) "key101" 2) "key102" 优点:✅ ​​非阻塞​​,不会长时间影响 Redis 服务。✅ ​​可控制每次返回的数量​​,降低单次操作开销。✅ ​​支持模糊匹配​​(通过 MATCH)。缺点:⚠️ ​​不保证强一致性​​:在遍历过程中,如果有 key 被增删改,可能会看到重复的 key 或者遗漏某些 key,但对大多数场景是可以接受的。⚠️ ​​需要客户端自行处理游标和多次调用​​。三、结合语言客户端使用 SCAN几乎所有 Redis 官方客户端(如 Python、Java、Node.js 等)都封装了 SCAN的迭代功能,使用起来更加方便。1. Python(redis-py): import redis r = redis.StrictRedis(host='localhost', port=6379, db=0) # 使用 scan_iter 方法(推荐,内部封装了 SCAN) for key in r.scan_iter(match="*", count=100): print(key.decode('utf-8')) scan_iter是一个生成器,会自动处理游标和多次 SCAN 调用,简化开发。2. Java(Jedis)示例: import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; public class RedisScanExample { public static void main(String[] args) { Jedis jedis = new Jedis("localhost"); String cursor = "0"; ScanParams scanParams = new ScanParams().count(100).match("*"); do { ScanResult<String> scanResult = jedis.scan(cursor, scanParams); for (String key : scanResult.getResult()) { System.out.println(key); } cursor = scanResult.getCursor(); } while (!cursor.equals("0")); } } 四、其他注意事项与建议1. ​​避免在高峰期执行大规模遍历​​即使使用 SCAN,如果 key 数量极大(比如上千万),仍然可能造成一定负载。建议在业务低峰期进行,或者采用分片/分布式方式处理。2. ​​考虑使用 Redis 的 SCAN+ TYPE+ 具体命令​​如果你不仅想遍历 key,还想获取每个 key 的 value 或类型,可以结合 TYPE命令以及 GET/ HGETALL/ SMEMBERS等,但要注意:这会进一步增加 Redis 和客户端的负载。尽量不要在遍历过程中对 key 执行写入或删除操作,避免数据不一致。3. ​​大 key 问题​​如果你的 key 中包含大 value(如大 Hash、大 List 等),在遍历时获取其内容可能导致网络和内存问题,建议提前识别并优化大 key。4. ​​使用 Redis 的 dbsize查看 key 总数(仅总数,不列出 key)​​ 127.0.0.1:6379> DBSIZE (integer) 1234567 这可以让你了解大致有多少 key,为遍历做准备,但注意它只是返回一个近似值。五、总结一下下方法是否阻塞是否推荐适用场景KEYS *是❌ 不推荐仅用于测试或极小数据量环境SCAN否✅ 推荐生产环境,安全遍历所有 key ​​生产环境一定要使用 SCAN,并尽量使用客户端提供的封装方法(如 scan_iter)。​​ 
  • Redisson 的 watchdog 什么情况下可能会失效?
    Redisson 的 watchdog 什么情况下可能会失效?
  • Redisson 中为什么要废弃 RedLock,该用啥?
    Redisson 中为什么要废弃 RedLock,该用啥?
  • Redis Cluster 中使用事务和 Iua 有什么限制?
    Redis Cluster 中使用事务和 Iua 有什么限制?
总条数:551 到第
上滑加载中