Ответы:
Это невозможно из соображений простоты Redis .
Куот Антирез, создатель Redis:
Привет, это невозможно, либо используйте другой ключ верхнего уровня для этого конкретного поля, либо сохраните вместе с поданным другим полем с истечением времени, выберите оба и дайте приложению понять, действительно ли он все еще действителен или нет, на основе Текущее время.
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
. Опять же, вам необходимо принять во внимание производительность этого подхода для вашего конкретного сценария.
Еще несколько ссылок:
Существует 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
Этот подход весьма полезен.
Это возможно в KeyDB, который является форком Redis. Поскольку это вилка, она полностью совместима с Redis и работает как капля замены.
Просто используйте команду EXPIREMEMBER. Он работает с наборами, хешами и отсортированными наборами.
EXPIREMEMBER keyname подключ [время]
Вы также можете использовать TTL и PTTL, чтобы увидеть срок действия
Подраздел имени ключа TTL
Дополнительная документация доступна здесь: https://docs.keydb.dev/docs/commands/#expiremember
Что касается реализации 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);
}
})
}
});
Array.filter
для создания массива keys
для удаления из хэша, а затем передать его client.hdel(HASH_NAME, ...keys)
за один вызов.
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Ты можешь. Вот пример.
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
Для этого вы можете хранить ключи / значения в Redis по-другому, просто добавляя префикс или пространство имен к вашим ключам при их сохранении, например, "hset_"
Получите ключ / значение, GET hset_key
равноеHGET hset key
Добавьте ключ / значение, SET hset_key value
равноеHSET hset key
Получить все ключи KEYS hset_*
равноHGETALL hset
Получить все валы нужно за 2 операции, сначала получить все ключи, KEYS hset_*
затем получить значение для каждого ключа
Добавьте ключ / значение с TTL или истечение срока действия, о котором идет речь:
SET hset_key value
EXPIRE hset_key
Примечание : KEYS
будет искать соответствующий ключ во всей базе данных, что может повлиять на производительность, особенно если у вас большая база данных.
Примечание:
KEYS
будет искать соответствующий ключ во всей базе данных, что может повлиять на производительность, особенно если у вас большая база данных. while SCAN 0 MATCH hset_*
может быть лучше, если он не блокирует сервер, но все же производительность является проблемой в случае большой базы данных.
Вы можете создать новую базу данных для отдельного хранения этих ключей, срок действия которых истекает, особенно если это небольшой набор ключей.
Спасибо @DanFarrell, который подчеркнул проблему производительности, связанную с
KEYS
hashset
... получить O (1) установить O (1) получить все O (n)
O(n)
для количества вещей в наборе, KEYS
для количества вещей в БД.
scan 0 match namespace:*
может быть лучше, если он не блокирует сервер
У нас была та же проблема, о которой здесь говорилось.
У нас есть хэш Redis, ключ к хеш-записям (парам имя / значение), и нам нужно было хранить индивидуальное время истечения срока для каждой хеш-записи.
Мы реализовали это, добавив n байтов префиксных данных, содержащих закодированную информацию об истечении срока действия, когда мы записываем значения записи хэша, мы также устанавливаем срок действия ключа на момент, содержащийся в записываемом значении.
Затем, при чтении, мы декодируем префикс и проверяем срок его действия. Это дополнительные накладные расходы, однако чтение по-прежнему O (n), и весь ключ истечет, когда истечет последняя запись хэша.
Вы можете использовать уведомления Redis Keyspace, используя psubscribe
и "__keyevent@<DB-INDEX>__:expired"
.
При этом каждый раз, когда истечет срок действия ключа, вы будете получать сообщение, опубликованное в вашем соединении Redis.
Что касается вашего вопроса, в основном вы создаете временный «нормальный» ключ, используя set
время истечения срока в с / мс. Он должен соответствовать имени ключа, который вы хотите удалить в своем наборе.
Поскольку ваш временный ключ будет опубликован в вашем соединении Redis с сохранением, "__keyevent@0__:expired"
когда истечет срок его действия, вы можете легко удалить свой ключ из исходного набора, так как в сообщении будет указано имя ключа.
Простой пример на практике на этой странице: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
документ: https://redis.io/topics/notifications (ищите флаг xE)
Вы можете использовать Sorted Set в redis, чтобы получить контейнер TTL с отметкой времени в качестве оценки. Например, всякий раз, когда вы вставляете строку события в набор, вы можете установить его счет на время события. Таким образом, вы можете получить данные любого временного окна, позвонив
zrangebyscore "your set name" min-time max-time
Более того, мы можем истечь, используя zremrangebyscore "your set name" min-time max-time
для удаления старых событий.
Единственным недостатком здесь является то, что вам придется выполнять служебные обязанности стороннего процесса, чтобы поддерживать размер набора.
Вы можете легко истечь хэши Redis, например, используя python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Это истекут все дочерние ключи в хэш hashed_user через 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)
hset
ребенок не полный hset
.