Redis中的Scan命令非阻塞的查看数据信息

本文探讨了在Redis中keys与scan命令的区别,keys命令虽简单但可能导致服务卡顿,而scan命令通过游标机制非阻塞地遍历key,更适用于生产环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

✍Redis中有一个经典的问题,在巨大的数据量的情况下,做类似于查找符合某种规则的Key的信息,这里就有两种方式:

  • keys命令,简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代价越大,产生的阻塞时间越长。
  • scan命令,以非阻塞的方式实现key值的查找,绝大多数情况下是可以替代keys命令的,可选性更强,推荐此方式。

指令示例
Redis 提供了一个简单暴力的指令 keys 用来列出所有满足特定正则字符串规则的 key。
查询指令:

127.0.0.1:1>keys key*

查询结果:

  1. “key3”
  2. “key6”
  3. “key1”
  4. “key7”
  5. “key9”
  6. “key8”
  7. “key4”
  8. “key2”
  9. “key5”

这个指令使用非常简单,提供一个简单的正则字符串即可,但是有很明显的两个缺点。

  • 没有 offset、limit 参数,一次性吐出所有满足条件的 key,万一实例中有几百 w 个 key 满足条件,当你看到满屏的字符串刷的没有尽头时,你就知道难受了。
  • keys 算法是遍历算法,复杂度是 O(n),如果实例中有千万级以上的 key,这个指令就会导致 Redis 服务卡顿,所有读写 Redis 的其它的指令都会被延后甚至会超时报错,因为 Redis 是单线程程序,顺序执行所有指令,其它指令必须等到当前的 keys 指令执行完了才可以继续。
  • 建议生产环境屏蔽keys命令;

Redis 为了解决这个问题,它在 2.8 版本中加入了指令 scan 指令

scan 相比 keys 具备有以下特点:

  • 复杂度虽然也是 O(n),但是它是通过游标分步进行的,分次进行不会阻塞线程;
  • 提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是对增量式迭代命令的一种提示(hint),返回的结果可多可少;
  • 同 keys 一样,它也提供模式匹配功能;
  • 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;
  • 返回的结果可能会有重复,需要客户端去重,这点非常重要;
  • 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
  • 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零.

scan 基础使用

语法:SCAN cursor [MATCH pattern] [COUNT count]
初始执行scan命令例如scan 0。SCAN命令是一个基于游标的迭代器。
这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。当SCAN命令的游标参数被设置为0时,服务器将开始一次新的迭代,而当redis服务器向用户返回值为0的游标时,表示迭代已结束,这是唯一迭代结束的判定方式,而不能通过返回结果集是否为空判断迭代结束。

  • scan 参数提供了三个参数,第一个是 cursor 整数值,第二个是 key 的正则模式,第三个是遍历的 limit hint。
  • 第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。
  • 一直遍历到返回的 cursor 值为 0 时结束。

查询指令:

127.0.0.1:1>scan 0 match key* count 20

查询结果:
在这里插入图片描述
查询指令:

127.0.0.1:1>scan 21 match key* count 20

查询结果:
在这里插入图片描述
返回结果分为两个部分:

  • 第一部分即 1) :下一次迭代游标;
  • 第二部分即 2) :本次迭代结果集。

注意: limit值20 不是限定返回结果的数量,而是限定服务器单次遍历的字典槽位数量(约等于)。
scan 其他指令
scan 指令是一系列指令,除了可以遍历所有的 key 之外,还可以对指定的容器集合进行遍历。

  • zscan 遍历 zset 集合元素;
  • hscan 遍历 hash 字典的元素;
  • sscan 遍历 set 集合的元素。

设置redis的key值的注意事项
平时业务开发中,应尽量避免大key的产生
原因: 有时候会因为业务人员使用不当,在 Redis 实例中会形成很大的对象,比如一个很大的 hash,一个很大的 zset 这都是经常出现的。这样的对象对 Redis 的集群数据迁移带来了很大的问题,因为在集群环境下,如果某个 key 太大,会让数据导致迁移卡顿。另外在内存分配上,如果一个 key 太大,那么当它需要扩容时,会一次性申请更大的一块内存,这也会导致卡顿。如果这个大 key 被删除,内存会一次性回收,卡顿现象会再一次产生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

能先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值