Подтвердить что ты не робот

Как "EXPIRE" дочерний ключ "HSET" в redis?

Мне нужно закончить все ключи в redis хэш, которые старше 1 месяца.

4b9b3361

Ответ 1

Это невозможно, ради простоты Redis.

Квот Антирез, создатель Redis:

Привет, это невозможно, либо использовать другой ключ верхнего уровня для этого конкретного поля, либо сохранить вместе с поданным другим полем со временем истечения, получить оба и позволить приложению понять, если он все еще действителен или не основан на Текущее время.

Ответ 2

Redis не поддерживает наличие TTL для хэшей, кроме верхней клавиши, что приведет к истечению всего хэша. Если вы используете сегментированный кластер, вы можете использовать другой подход. Этот подход не может быть полезен во всех сценариях, и характеристики производительности могут отличаться от ожидаемых. Еще стоит упомянуть:

При наличии хеша структура в основном выглядит следующим образом:

hash_top_key
  - child_key_1 -> some_value
  - child_key_2 -> some_value
  ...
  - child_key_n -> some_value

Поскольку мы хотим добавить TTL к дочерним клавишам, мы можем переместить их в верхние клавиши. Главное, чтобы ключ теперь был комбинацией hash_top_key и дочернего ключа:

{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value

Мы специально используем обозначение {}. Это позволяет всем этим клавишам находиться в одном hash slot. Вы можете прочитать больше об этом здесь: https://redis.io/topics/cluster-tutorial

Теперь, если мы хотим выполнить ту же операцию с хешами, мы могли бы сделать:

HDEL hash_top_key child_key_1 => DEL {hash_top_key}child_key_1

HGET hash_top_key child_key_1 => GET {hash_top_key}child_key_1

HSET hash_top_key child_key_1 some_value => SET {hash_top_key}child_key_1 some_value [some_TTL]

HGETALL hash_top_key => 
  keyslot = CLUSTER KEYSLOT {hash_top_key}
  keys = CLUSTER GETKEYSINSLOT keyslot n
  MGET keys

Интересным здесь является HGETALL. Сначала мы получаем hash slot для всех наших дочерних ключей. Затем мы получаем ключи для этого конкретного hash slot и, наконец, получаем значения. Здесь нужно быть осторожным, поскольку для этого n может быть больше ключей hash slot, а также могут быть ключи, которые нам не интересны, но у них одинаковые hash slot. На самом деле мы могли бы написать сценарий Lua для выполнения этих действий на сервере, выполнив команду EVAL или EVALSHA. Опять же, вы должны принять во внимание эффективность этого подхода для вашего конкретного сценария.

Еще несколько ссылок:

Ответ 3

Существует Java-инфраструктура Redisson, которая реализует хэш-объект Map с поддержкой записи TTL. Он использует hmap и zset Redis объекты под капотом. Пример использования:

RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days

Этот подход весьма полезен.

Ответ 4

Что касается реализации NodeJS, я добавил пользовательское поле expiryTime в объект, который я сохраняю в HASH. Затем по истечении определенного периода времени я очищаю устаревшие записи HASH, используя следующий код:

client.hgetall(HASH_NAME, function(err, reply) {
    if (reply) {
        Object.keys(reply).forEach(key => {
            if (reply[key] && JSON.parse(reply[key]).expiryTime < (new Date).getTime()) {
                client.hdel(HASH_NAME, key);
            }
        })
    }
});

Ответ 5

Вы можете хранить ключи/значения в Redis по-разному, чтобы достичь этого, просто добавив префикс или пространство имен к своим ключам, когда вы сохраняете их, например, "hset_"

  • Получить ключ/значение GET hset_key равно HGET hset key

  • Добавить ключ/значение SET hset_key value равно SET hset_key value HSET hset key

  • Получить все ключи KEYS hset_* равно HGETALL hset

  • Получить все значения нужно за 2 операции, сначала получить все ключи KEYS hset_* затем получить значение для каждого ключа

  • Добавьте ключ/значение с TTL или expire, что является темой вопроса:

 SET hset_key value
 EXPIRE hset_key

Примечание. KEYS поиск соответствия ключа во всей базе данных, что может повлиять на производительность, особенно если у вас большая база данных.

Замечания:

  • KEYS проверит соответствие ключа во всей базе данных, что может повлиять на производительность, особенно если у вас большая база данных. в то время как SCAN 0 MATCH hset_* может быть лучше, если он не блокирует сервер, но все же производительность является проблемой в случае большой базы данных.

  • Вы можете создать новую базу данных для отдельного хранения этих ключей, срок действия которых вы хотите истечь, особенно если они представляют собой небольшой набор ключей.

Спасибо @DanFarrell, который выделил проблему производительности, связанную с KEYS

Ответ 6

Вы можете. Вот пример.

redis 127.0.0.1:6379> hset key f1 1
(integer) 1
redis 127.0.0.1:6379> hset key f2 2
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> expire key 10
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key

Используйте EXPIRE или EXPIREAT команда.

Если вы хотите истечь определенные ключи в хеш старше, чем 1 месяц. Это невозможно. Команда redis expire предназначена для всех ключей в хеше. Если вы установите ежедневный хеш-ключ, вы можете установить время жизни клавиш.

hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2

Ответ 7

Вы можете легко истечь хэши Redis, например, используя python

import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)

Это истечет срок действия всех дочерних ключей в hash_hser через 10 секунд

то же самое от redis-cli,

127.0.0.1:6379> HMSET testt username wlc password P1pp0 age 34
OK
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
127.0.0.1:6379> expire testt 10
(integer) 1
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"

через 10 секунд

127.0.0.1:6379> hgetall testt
(empty list or set)

Ответ 8

Вы можете использовать Redis Keyspace Notification, используя psubscribe и "[email protected]<DB-INDEX>__:expired".

При этом каждый раз, когда истекает срок действия ключа, вы будете публиковать сообщение о своем подключении к Redis.

Относительно вашего вопроса в основном вы создаете временный "нормальный" ключ, используя set со временем истечения в с/мс. Он должен соответствовать названию ключа, который вы хотите удалить в своем наборе.

Поскольку ваш временный ключ будет опубликован в вашем подключении redis, содержащем "[email protected]__:expired" когда он истек, вы можете легко удалить свой ключ из исходного набора, так как в сообщении будет указано имя ключа.

Простой пример из практики на этой странице: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3

doc: https://redis.io/topics/notifications (ищите флаг xE)

Ответ 9

Вы можете использовать Sorted Set в Redis, чтобы получить контейнер TTL с отметкой времени в качестве оценки. Например, всякий раз, когда вы вставляете строку события в набор, вы можете установить ее счет на время события. Таким образом, вы можете получить данные любого временного окна, вызвав zrangebyscore "your set name" min-time max-time

Более того, мы можем сделать истечение срока действия, используя zremrangebyscore "your set name" min-time max-time для удаления старых событий.

Единственным недостатком здесь является то, что вы должны вести домашнюю работу из аутсайдерского процесса, чтобы поддерживать размер набора.

Ответ 10

Здесь обсуждалась та же проблема.

У нас есть хэш Redis, ключ к хеш-записям (пары имя/значение), и нам нужно было хранить индивидуальное время истечения для каждой хеш-записи.

Мы реализовали это, добавив n байтов данных префикса, содержащих закодированную информацию об истечении срока действия, когда мы записываем значения хеш-записи, мы также устанавливаем срок действия ключа в момент, содержащийся в записываемом значении.

Затем, при чтении, мы декодируем префикс и проверяем его срок действия. Это дополнительные накладные расходы, однако чтения по-прежнему O (n) и весь ключ истечет, когда истек срок действия последней записи хеша.