Redis
 sql >> база данни >  >> NoSQL >> Redis

Как да получите същия ранг за същите резултати в ZRANK на Redis?

Всяко истинско решение трябва да отговаря на изискванията, които донякъде липсват в оригиналния въпрос. Първият ми отговор предполагаше малък набор от данни, но този подход не се мащабира, тъй като се извършва плътно класиране (например чрез Lua) поне в O(N).

Така че, ако приемем, че има много потребители с резултати, посоката, която for_stack предложи, е по-добра, в която се комбинират множество структури от данни. Мисля, че това е същината на последната му забележка.

За да съхранявате резултатите на потребителите, можете да използвате хеш. Докато концептуално можете да използвате един ключ за съхраняване на хеш на всички потребителски резултати, на практика бихте искали да хеширате хеша, така че да се мащабира. За да опростя този пример, ще игнорирам мащабирането на хеш.

Ето как бихте добавили (актуализирате) потребителски резултат в Lua:

local hscores_key = KEYS[1]
local user = ARGV[1]
local increment = ARGV[2]
local new_score = redis.call('HINCRBY', hscores_key, user, increment)

След това искаме да проследим текущия брой потребители на дискретна стойност на резултата, така че да запазим друг хеш за това:

local old_score = new_score - increment
local hcounts_key = KEYS[2]
local old_count = redis.call('HINCRBY', hcounts_key, old_score, -1)
local new_count = redis.call('HINCRBY', hcounts_key, new_score, 1)

Сега, последното нещо, което трябва да поддържаме, е ранга на резултат, с сортиран набор. Всеки нов резултат се добавя като член в zset и резултати, които нямат повече потребители, се премахват:

local zdranks_key = KEYS[3]
if new_count == 1 then
  redis.call('ZADD', zdranks_key, new_score, new_score)
end
if old_count == 0 then
  redis.call('ZREM', zdranks_key, old_score)
end

Сложността на този скрипт от 3 части е O(logN) поради използването на сортирания набор, но имайте предвид, че N е броят на дискретните стойности на резултата, а не на потребителите в системата. Получаването на плътно класиране на потребителя се извършва чрез друг, по-кратък и опростен скрипт:

local hscores_key = KEYS[1]
local zdranks_key = KEYS[2]
local user = ARGV[1]

local score = redis.call('HGET', hscores_key, user)
return redis.call('ZRANK', zdranks_key, score)


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. защо е толкова бавен със 100 000 записа при използване на конвейер в redis?

  2. Управление на връзката с redis от Python

  3. Джедаите Променят ли семантиката на Redis?

  4. Как да получите обратно повикване, когато ключът изтече в REDIS

  5. обработка на промени в пространството на имена по време на десериализация на JSON низ