Redis中的SCAN vs KEYS性能

Jak*_*ake 25 redis

许多来源,包括Redis官方文档,都指出,KEYS由于可能存在阻塞,在生产环境中使用该命令是一个坏主意.如果已知数据集的近似大小,是否SCAN有任何优势KEYS

例如,考虑一个最多100个表格的数据库,data:number:X其中X是一个整数.如果我想要检索所有这些,我可能会使用该命令KEYS data:number:*.这会比使用慢得多SCAN 0 MATCH data:number:* COUNT 100吗?或者这两个命令在这种情况下基本相同?是否可以准确地说这SCAN是可取的,KEYS因为它可以防止出现意外大量集合的情况?

Mat*_*zer 36

您不应该关心当前的命令执行,而是关注对所有其他命令的影响,因为Redis使用单个线程处理命令(即在执行命令时,所有其他命令需要等待直到执行一个命令).

虽然keys或者scan可能在您的情况下单独执行类似或相同的性能,但阻止Redis的几毫秒将显着降低整体I/O.

这是keys用于开发目的和scan生产环境的主要原因.

OP说:

"虽然键或扫描可能会在您的情况下单独执行相似或相同的性能,但阻止Redis的几毫秒将显着降低整体I/O." - 这句话似乎表明一个命令阻止Redis,另一个命令不阻止,但情况并非如此.如果我保证100次调用KEYS的结果,它会以什么方式比SCAN更糟?为什么你觉得一个命令更容易阻塞?

当您可以对搜索进行分页时,应该会有很大的不同.在一次通过中被迫获得100个密钥与能够实现分页并获得100个密钥(10乘10(或50和50))不同.这种非常小的中断可以让应用层发送的其他命令由Redis处理.看看Redis官方文档中有关于此的内容:

由于这些命令允许增量迭代,每次调用只返回少量元素,因此可以在生产中使用它们,而不会像KEYS或SMEMBERS这样的命令的缺点,这些命令可能会在被调用时长时间(甚至几秒钟)阻塞服务器钥匙或元素的大集合

.

  • 非常真实。但是,只有 100 个键可能没有实际区别。另外,应该注意`SCAN` 的`COUNT` 参数只是一个提示而不是一个指令。 (2认同)
  • @ItamarHaber BTW我喜欢用正确的方法设计解决方案,而不是依赖"这不会永远不会发生".另一方面,你不认为如果你需要在全局键空间中使用`keys`或`scan`,听起来有更好的解决方案来存储数据并通过页面访问它吗?`lrange`,`zrange`:D (2认同)

Kan*_*mar 9

  1. 除了分页( count )之外,KEYS 和 SCAN 之间没有性能差异,从 redis 到客户端传输(IO)的字节数将在分页中控制。

  2. count 选项本身有自己的规范,有时您不会获取数据,但扫描光标仍然打开,因此将在下一次迭代中获取数据。因此,计数选项应该是合理的数量,例如 200 到最大值,以避免多次往返时间。我认为这个值取决于数据库中键的总数。

  3. 与 KEYS 相比,当我们在 LUA 中使用 SCAN 时,没有任何区别,尽管不涉及 IO,但两者仍然会阻塞其他调用,直到迭代整个大集合。我没试过这个,我猜是的。

  • 当您投反对票时,请写下您的评论,以便我也学习和纠正。 (25认同)

Bas*_*wer 6

答案在SCAN文档中

这些命令允许增量迭代,每次调用仅返回少量元素,它们可以在生产中使用,而不会受到诸如此类的不利影响,KEYS或者SMEMBERS在针对大量集合调用时可能会阻塞服务器很长时间(甚至几秒钟)键或元素。

因此,要求提供少量数据,而不是获取全部数据

正如MatíasFidemraizer所指出的那样,Redis是单线程的,并且KEYS是一个阻塞调用,因此会阻塞任何传入的操作请求,直到执行KEYS完成。

无论您的数据是否小,应用最佳实践都不会造成伤害。

  • 澄清-Redis中的所有命令都在服务器上阻塞,因为它是单线程的。密钥很可能会长时间阻塞,以试图在一次操作中获取所有密钥,而不是在几次操作中将少量密钥发送回去。 (2认同)