Redis сканирование пропуская ключи
Я использую predis (с laravel, если это имеет какое-то значение) php клиент для работы с Redis.
Мне нужно получить все ключи от Redis, которые соответствуют определенному префиксу, и я делаю это так:
$keys = [];
foreach (new Iterator\Keyspace($this->redis(), Cache::KEY_PREFIX.'*') as $key) {
$keys[] = $rate_key;
}
После того, как работа с этими ключами завершена, операция повторяется - я снова включаю эти ключи в цикл. Я заметил, что после нескольких итераций некоторые ключи не включаются в массив $ keys.
Самое странное, что исчезающие ключи никогда не появляются в следующих итерациях. Перезапуск процесса php (это демон) решает проблему.
Я использую Redis 3.0.2 с Predis 1.0 и PHP 5.4
PS В цикле над ключами я изменяю значения для некоторых из них. Однако я не удаляю ключи.
1 ответ
В самом деле! Это потому, что SCAN работает таким образом, цитируя документацию Redis:
Однако, хотя блокирующие команды, такие как SMEMBERS, могут предоставить все элементы, которые являются частью набора в данный момент, семейство команд SCAN предлагает только ограниченные гарантии для возвращаемых элементов, поскольку коллекция, которую мы постепенно увеличиваем, может изменяться в процессе итерации.,
Однако, поскольку SCAN имеет очень мало связанных состояний (только курсор), он имеет следующие недостатки: данный элемент может возвращаться несколько раз. Приложение должно обрабатывать случай дублированных элементов, например, используя только возвращенные элементы для выполнения операций, которые безопасны при повторном применении несколько раз.
Таким образом, вы можете использовать хотеть использовать array_unique($keys) после foreach
,
Чтобы понять, почему итерация работает таким образом, лучше всего прочитать эту часть документации Redis.