Производительность 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

  1. Не существует разницы в производительности между KEYS и SCAN, кроме разбивки на страницы (количество), где количество байтов, переданных (IO) от redis к клиенту, будет контролироваться в разбивке на страницы.

  2. У параметра count у него есть собственная спецификация, где иногда вы не получите данные, но все же курсор сканирования включен, поэтому данные будут получены в следующих итерациях. Таким образом, для параметра count должно быть разумное количество, скажем 200, до макс, чтобы избежать множественного времени в оба конца. Я думаю, что это значение зависит от общего количества ключей в вашем db.

  3. Нет смысла/разницы, когда мы используем SCAN в LUA по сравнению с KEYS, хотя не задействовано IO, но оба блокируют другие вызовы до тех пор, пока вся большая коллекция не повторится. Я не пробовал, думаю.