Возможно ли сделать SET
ключей redis без удаления их существующего ttl? Единственный способ, которым я знаю в настоящее время, - это узнать ttl и сделать SETEX
, но это кажется менее точным.Как обновить значение redis, не влияя на оставшийся TTL?
ответ
Согласно Redis documentation, команда SET
удаляет TTL, поскольку ключ перезаписывается.
Однако вы можете использовать команду EVAL
, чтобы оценить сценарий Lua, чтобы сделать это автоматически для вас.
В приведенном ниже скрипте проверяется значение TTL ключа, если значение положительное, оно вызывает SETEX
с новым значением и с использованием оставшегося TTL.
локальная ТТЛ = redis.call ('ТТЛ', ARGV [1]), если ТТЛ> 0, то возвращают redis.call ('SETEX', ARGV [1], TTL, ARGV [2]) конец
Пример:
> установить ключ 123
OK
> истекают ключ 120
(целое число) 1
... через несколько секунд
> ТТЛ ключ
(целое число) 97
> Eval «локальная ТТЛ = redis.call (» ttl ', ARGV [1]), если ttl> 0, то верните redis.call (' SETEX ', ARGV [1], ttl, ARGV [2]) end "0 ключ 987
OK
> ТТЛ ключ
> получить ключ
"987"
Может быть INCR
, INCRBY
, DECR
и т.д. могут помочь вам. Они не изменяют TTL.
> setex test 3600 13
OK
> incr test
(integer) 14
> ttl test
(integer) 3554
Вот функция, чтобы проверить существующий TTL и использовать его в случае необходимости.
expire arguments 0 - использовать существующее время истечения срока действия,> 0 - установить новое время истечения срока действия, неопределенное - без истечения срока.
/**
* update an item. preserve ttl or set a new one
* @param {object} handle the redis handle
* @param {string} key the key
* @param {*} content the content - if an object it'll get stringified
* @param {number||null} expire if a number > 0 its an expire time, 0
means keep existing ttl, undefined means no expiry
* @return {Promise}
*/
ns.updateItem = function (handle , key , content,expire) {
// first we have to get the expiry time if needed
return (expire === 0 ? handle.ttl(key) : Promise.resolve (expire))
.then (function (e) {
// deal with errors retrieving the ttl (-1 no expiry, -2 no existing record)
var ttl = e > 0 ? e : undefined;
// stingify the data if needed
var data = typeof content === "object" ? JSON.stringify(content) : content;
// set and apply ttl if needed
return ttl ? handle.set (key, data , "EX", ttl) : handle.set (key,data);
});
};
Можно изменить значение TTL, не влияя на его ключа от изменения значения биты один за другим в соответствии с новым значением, используя SETBIT.
Недостаток этого подхода, однако, очевидно, влияет на производительность, особенно если значение довольно велико.
ПРИМЕЧАНИЕ: Желательно, чтобы выполнить это в транзакции (мульти EXEC) блокировать
Поддержание TTL сами по
- Определение текущего TTL
- Установить новое значение
Восстановление TTL после заданного значения
, очевидно, не объявление видимые из-за неизвестной долговечности выполняемых команд.
Другой альтернативой является использование List как тип данных, и после добавления нового значения в список с использованием LPUSHLTRIM поддерживать размер списка в один элемент. Это не изменит TTL на ключ.