Производительность SCAN vs KEYS в Redis
Некоторые источники, включая официальную документацию Redis, отмечают, что использование команды KEYS
- плохая идея в производственных средах из-за возможной блокировки. Если приблизительный размер набора данных известен, имеет ли SCAN
какое-либо преимущество перед KEYS
?
Например, рассмотрите базу данных с не более чем 100 ключами данных формы data:number:X
где X
- целое число. Если я хочу получить все эти данные, я могу использовать команду KEYS data:number:*
. Будет ли это значительно медленнее, чем использование данных SCAN 0 MATCH data:number:* COUNT 100
? Или две команды по существу эквивалентны в этом случае? Можно ли сказать, что SCAN
предпочтительнее KEYS
потому что он защищает от сценария, в котором будет возвращен неожиданно большой набор?
Ответы
Ответ 1
Вы не должны заботиться о текущем выполнении команды, а о влиянии на все остальные команды, поскольку Redis обрабатывает команды с использованием одного потока (т.е. Во время выполнения команды все остальные должны ждать, пока не исполнится один конец).
Хотя keys
или scan
могут предоставить вам аналогичную или идентичную производительность, выполненную самостоятельно в вашем случае, некоторые миллисекунды, блокирующие Redis, значительно уменьшат общий ввод-вывод.
Это основная причина использования keys
для целей разработки и scan
в производственных средах.
ОП сказал:
"Хотя клавиши или сканирование могут предоставить вам аналогичную или идентичную производительность, выполненную самостоятельно в вашем случае, некоторые миллисекунды, блокирующие Redis, значительно уменьшат общий ввод-вывод". - Это предложение указывает, что одна команда блокирует Redis, а другая - нет, чего не может быть. Если мне гарантировано 100 результатов моего звонка в KEYS, каким образом это хуже, чем SCAN? Почему вы чувствуете, что одна команда более подвержена блокированию?
Должна быть хорошая разница, если вы можете разбивать страницы на страницы. Это не то же самое, что заставлять забирать 100 ключей за один проход, чем возможность реализовать разбиение на страницы и получить 100 ключей, 10 на 10 (или 50 и 50). Это очень маленькое прерывание может позволить другим командам, посылаемым прикладным уровнем, обработать Redis. Посмотрите, что говорится в официальной документации Redis:
Поскольку эти команды допускают инкрементную итерацию, возвращая только небольшое количество элементов для каждого вызова, их можно использовать в производстве без недостатков команд, таких как KEYS или SMEMBERS, которые могут блокировать сервер в течение длительного времени (даже нескольких секунд) при вызове большие коллекции ключей или элементов
,
Ответ 2
Ответ приведен в документации SCAN
Эти команды допускают инкрементную итерацию, возвращая только небольшое количество элементов для каждого вызова, их можно использовать в производстве без недостатка команд, таких как KEYS
или SMEMBERS
которые могут блокировать сервер в течение длительного времени (даже нескольких секунд) при вызове с большим коллекции ключей или элементов.
Так что попросите небольшие куски данных, а не получите их все
Также, как указал Матиас Фидемайзер, Redis является однопоточным, а KEYS
является блокирующим вызовом, тем самым блокируя любые входящие запросы для работы до тех пор, пока не будет выполнено выполнение KEYS
.
Независимо от того, ваши данные малы или нет, никогда не помешает применять лучшие практики.
Ответ 3
-
Не существует разницы в производительности между KEYS и SCAN, кроме разбивки на страницы (количество), где количество байтов, переданных (IO) от redis к клиенту, будет контролироваться в разбивке на страницы.
-
У параметра count у него есть собственная спецификация, где иногда вы не получите данные, но все же курсор сканирования включен, поэтому данные будут получены в следующих итерациях. Таким образом, для параметра count должно быть разумное количество, скажем 200, до макс, чтобы избежать множественного времени в оба конца. Я думаю, что это значение зависит от общего количества ключей в вашем db.
-
Нет смысла/разницы, когда мы используем SCAN в LUA по сравнению с KEYS, хотя не задействовано IO, но оба блокируют другие вызовы до тех пор, пока вся большая коллекция не повторится. Я не пробовал, думаю.