许多来源,包括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这样的命令的缺点,这些命令可能会在被调用时长时间(甚至几秒钟)阻塞服务器钥匙或元素的大集合
.
除了分页( count )之外,KEYS 和 SCAN 之间没有性能差异,从 redis 到客户端传输(IO)的字节数将在分页中控制。
count 选项本身有自己的规范,有时您不会获取数据,但扫描光标仍然打开,因此将在下一次迭代中获取数据。因此,计数选项应该是合理的数量,例如 200 到最大值,以避免多次往返时间。我认为这个值取决于数据库中键的总数。
与 KEYS 相比,当我们在 LUA 中使用 SCAN 时,没有任何区别,尽管不涉及 IO,但两者仍然会阻塞其他调用,直到迭代整个大集合。我没试过这个,我猜是的。
答案在SCAN文档中
这些命令允许增量迭代,每次调用仅返回少量元素,它们可以在生产中使用,而不会受到诸如此类的不利影响,
KEYS或者SMEMBERS在针对大量集合调用时可能会阻塞服务器很长时间(甚至几秒钟)键或元素。
因此,要求提供少量数据,而不是获取全部数据
正如MatíasFidemraizer所指出的那样,Redis是单线程的,并且KEYS是一个阻塞调用,因此会阻塞任何传入的操作请求,直到执行KEYS完成。
无论您的数据是否小,应用最佳实践都不会造成伤害。