Rozwiązaniem jest użycie skryptu Lua:
local time = redis.call('TIME')
local ts = time[1]..string.format('%06d', time[2])
return redis.call('ZADD', KEYS[1], ts, ARGV[1])
Tutaj używamy Redisa TIME
Komenda. Polecenie zwraca:
- czas uniksowy w sekundach
- mikrosekundy
Możemy więc połączyć te dwa i użyć mikrosekundowego znacznika czasu. Musimy zerować część dotyczącą mikrosekund.
Ponieważ posortowane zestawy są dobre z wartościami całkowitymi do 2^53, nasz znacznik czasu jest bezpieczny aż do roku 2255.
Jest to bezpieczne dla klastra Redis, ponieważ przechowujemy je w jednym kluczu. Aby użyć wielu kluczy, upewnij się, że umieszczasz je w tym samym węźle za pomocą tagów hash, jeśli chcesz porównać sygnatury czasowe.
Możesz zmodyfikować skrypt, aby używał rozdzielczości niższej niż mikrosekundy.
Tutaj EVAL
polecenie, proste hasło i wartość jako argumenty, nie ma potrzeby wcześniejszego tworzenia posortowanego zestawu:
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
Jak zawsze, możesz chcieć załadować skrypt i użyć 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
Uwaga na temat wersji Redis. Jeśli używasz:
- Redis Wersja przed 3.2:przepraszam, nie możesz użyć
TIME
(polecenie niedeterministyczne), a następnie pisać za pomocąZADD
. - Redis Wersja większa niż 3.2, ale <5.0:Dodaj
redis.replicate_commands()
na górze skryptu. Zobacz skrypty jako czyste funkcje - Redis 5.0 w górę:jesteś dobry.