Решение заключается в использовании сценария Lua:
local time = redis.call('TIME')
local ts = time[1]..string.format('%06d', time[2])
return redis.call('ZADD', KEYS[1], ts, ARGV[1])
Здесь мы используем команду Redis TIME
. Команда возвращает:
- unix время в секундах
- микросекунды
Таким образом, мы можем объединить эти два и использовать метку времени микросекунды. Нам нужно заполнить микросекундами нулями.
Поскольку отсортированные наборы хороши с целыми значениями до 2 ^ 53, наша временная метка безопасна вплоть до 2255 года.
Это Redis-Cluster-safe, поскольку мы храним в одном ключе. Чтобы использовать несколько ключей, обязательно поместите их на один и тот же узел, используя га sh теги , если вы хотите сравнить метки времени.
Вы можете изменить сценарий, чтобы использовать разрешение ниже микросекунды .
Здесь команда EVAL
, простой ключ передачи и значение в качестве аргументов, нет необходимости создавать отсортированный набор перед рукой:
EVAL "local time = redis.call('TIME') local ts = time[1]..string.format('%06d', time[2]) return redis.call('ZADD', KEYS[1], ts, ARGV[1])" 1 ssetKey myVal
Как всегда, вы можете захотеть загрузите скрипт и используйте EVALSHA
.
> SCRIPT LOAD "local time = redis.call('TIME') local ts = time[1]..string.format('%06d', time[2]) return redis.call('ZADD', KEYS[1], ts, ARGV[1])"
"81e366e422d0b09c9b395b5dfe03c03c3b7b3bf7"
> EVALSHA 81e366e422d0b09c9b395b5dfe03c03c3b7b3bf7 1 ssetKey myNewVal
(integer) 1
Примечание по версии Redis. Если вы используете:
- Версия Redis до 3.2: извините, вы не можете использовать
TIME
(недетерминированная c команда), а затем писать с ZADD
. - Версия Redis больше 3.2, но <5.0: добавьте <code>redis.replicate_commands() поверх скрипта. См. Сценарии как чистые функции
- Redis 5.0 и выше: вы хороши.