Я использую 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 Внутри цикла над ключами я изменяю значения для некоторых из них. Однако я не удаляю никаких ключей.
В самом деле! Это потому, что SCAN работает именно так, цитируя документацию Redis:
Тем не менее, в то время как блокирующие команды, такие как SMEMBERS, могут предоставить все элементы, которые являются частью Set в данный момент, команды команд SCAN предоставляют только ограниченные гарантии относительно возвращаемых элементов, поскольку коллекция, которую мы постепенно увеличиваем, может меняться в процессе итерации ,
Однако поскольку SCAN имеет очень мало ассоциированного состояния (только курсор), он имеет следующие недостатки: данный элемент может быть возвращен несколько раз. Это приложение должно обрабатывать случай дублированных элементов , например, только с использованием возвращаемых элементов для выполнения операций, которые являются безопасными при повторном применении несколько раз.
Поэтому вы можете захотеть использовать array_unique ($ keys) после foreach
.
Чтобы понять, почему итерация работает таким образом, лучше всего прочитать эту часть документации Redis .