sql >> Databáze >  >> NoSQL >> Redis

Jak získat stejnou hodnost za stejné skóre v Redis' ZRANK?

Jakékoli skutečné řešení musí odpovídat požadavkům, které v původní otázce jaksi chybí. Moje první odpověď předpokládala malý soubor dat, ale tento přístup se neškáluje, protože se provádí husté řazení (např. přes Lua) alespoň v O(N).

Takže za předpokladu, že existuje mnoho uživatelů se skóre, směr navrhovaný for_stack je lepší, ve kterém je kombinováno více datových struktur. Věřím, že toto je podstata jeho poslední poznámky.

Chcete-li uložit skóre uživatelů, můžete použít hash. Zatímco koncepčně můžete použít jeden klíč k uložení hash skóre všech uživatelů, v praxi byste chtěli hash hash, aby se škáloval. Aby byl tento příklad jednoduchý, budu ignorovat škálování hash.

Takto přidáte (aktualizujete) skóre uživatele v Lua:

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

Dále chceme sledovat aktuální počet uživatelů na jednotlivé hodnoty skóre, takže si pro to ponecháváme další hash:

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)

Nyní poslední věc, kterou musíme zachovat, je pořadí podle skóre se seřazenou sadou. Každé nové skóre je přidáno jako člen do zset a skóre, které nemá žádné další uživatele, je odstraněno:

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

Složitost tohoto třídílného skriptu je O(logN) kvůli použití Sorted Set, ale všimněte si, že N je počet diskrétních hodnot skóre, nikoli uživatelů v systému. Získání hustého hodnocení uživatele se provádí pomocí jiného, ​​kratšího a jednoduššího skriptu:

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. Jak vizualizovat použití Resque pomocí Node.js, WebSockets a Redis

  2. MongoDB vs MySQL

  3. PyMongo -- iterace kurzoru

  4. Řadit pomocí MongoEngine?