Получить случайное / любое значение из хэша Redis
У меня есть Redis-Hash с миллионами элементов, постоянно добавляющих новые. В php я запускаю бесконечный цикл для получения, обработки и удаления одного элемента из другого. Таким образом, мне нужно получить ключ любого существующего элемента (предпочтительно первый, вставленный в хеш, FiFo)
while($redis->hlen()) {
$key = ???
// process $key
}
Пока я знаю RANDOMKEY
и SRANDMEMBER
По команде я не нашел способа получить ключ хеша. HGETALL
а также HKEYS
из-за размера хэша, тоже не вариант. Мне нужна последовательная обработка. Помощь приветствуется.
1 ответ
Нет хитрости для доступа к случайному элементу (или первому, или последнему) данного хеш-объекта.
Если вам нужно перебрать объекты хеша, у вас есть несколько возможностей:
первый - это дополнить хеш другой структурой данных, которую вы можете разделить (например, список или zset). Если вы только добавляете элементы в хеш (и повторяете их удаление), списка достаточно. Если вы можете добавлять / удалять / обновлять элементы (и выполнять итерацию для их удаления), тогда требуется zset (отметка времени ставится как оценка). Оба списка zset могут быть нарезаны (lrange, zrange, zrangebyscore), поэтому легко выполнять итерации по ним по частям и поддерживать синхронизацию обеих структур данных.
второй - дополнить хеш другой структурой данных, поддерживающей подобные операции, такие как список или набор (lpop, rpop, spop). Вместо того, чтобы итерировать объект хеша, вы можете извлечь все объекты из вторичной структуры и соответствующим образом поддерживать объект хеша. Опять же, обе структуры данных должны быть синхронизированы.
третий - разбить хеш-объект на множество частей. На самом деле это эффективно использует память, потому что ваши ключи хранятся только один раз, и Redis может использовать оптимизацию памяти ziplist.
Так что вместо того, чтобы хранить ваш хеш как:
myobject -> { key1:xxxx, key2:yyyyy, key3:zzzz }
Вы можете хранить:
myobject:<hashcode1> -> { key1:xxxx, key3:zzzz }
myobject:<hashcode2> -> { key2:yyyy }
...
Чтобы вычислить дополнительный хеш-код, вы можете применить любую хеш-функцию к вашим ключам, которая предлагает хорошее распределение. В приведенном выше примере мы предполагаем, что key1 и key3 имеют одинаковое значение hashcode1, а key2 имеет значение hashcode2.
Вы можете найти больше информации об этом типе структур данных здесь:
Redis в 10 раз больше памяти, чем данные
Выходная мощность хеш-функции должна быть рассчитана таким образом, чтобы количество элементов на хеш-объект ограничивалось заданным значением. Например, если мы выберем 100 элементов в каждом хеш-объекте и нам нужно хранить 1 млн. Элементов, нам потребуется 10КБ. Чтобы ограничить количество элементов, достаточно просто использовать операцию по модулю для общей хеш-функции.
Преимущество заключается в том, что он будет компактным в памяти (используется ziplist), и вы можете легко итеративно выполнять итерацию по объектам хеш-функции, передавая по конвейеру hgetall+del для всех них:
hgetall myobject:0
... at most 100 items will be returned, process them ...
del myobject:0
hgetall myobject:1
... at most 100 items will be returned, process them ...
del myobject:1
...
Следовательно, вы можете выполнять итерацию фрагмента по фрагменту с гранулярностью, которая определяется выходной мощностью хеш-функции.