2011-01-30 8 views

risposta

12

L'unica opzione che penso sta iterando il set ordinato e calcolando il lato client somma.

+0

grazie! Sì, immagino che questo sia probabilmente troppo specifico di una funzionalità per Redis che si preoccupa di implementare ... esp. dato che forse non sto facendo qualcosa di consigliabile. Sto utilizzando un set zset per memorizzare gli ID regalo ricevuti dall'utente e gli ID utente di invio e lo SCORE è il numero di volte in cui lo stesso regalo è stato ricevuto dallo stesso mittente. Ad esempio, 'ZINCR 123: regali 1" 3 | 345 "' invia l'ID regalo 3 dall'utente 345 all'utente 123. Quindi, voglio ottenere il totale dei regali che un utente ha ricevuto. Vedere? Forse c'è un modo migliore per implementarlo? È come l'API dei regali di Facebook. Regole di Redis! :) Grazie di tutto! – ma11hew28

3

Se i set sono piccoli e non è necessario eseguire prestazioni killer, desidero semplicemente eseguire l'iterazione (zrange/zrangebyscore) e sommare i valori lato client.

Se, al contrario, si parla di molte migliaia - milioni di elementi, è sempre possibile mantenere un set di riferimento con totali parziali per ciascun utente e incrementarlo/diminuirlo man mano che i regali vengono inviati.

Quindi, quando fate la vostra ZINCR 123:gifts 1 "3|345", si potrebbe fare un comando ZINCR separato, che potrebbe essere qualcosa di simile:

ZINCR received-gifts 1 <user_id> 

Quindi, per ottenere il # dei doni ricevuti per un determinato utente, è sufficiente per eseguire uno Zscore:

ZSCORE received-gifts <user_id> 
+0

Il conteggio incrementale vince di gran lunga per i problemi online. La scansione deve essere utilizzata solo negli algoritmi offline, IMHO, poiché nessuno può prevedere la crescita futura del set di dati. Questa risposta dovrebbe essere quella accettata. Oh, e btw: si potrebbe scrivere un comando personalizzato che fa entrambi (aggiungendo a un set e incrementando il contatore, aggiornando un valore e regolando il contatore, eliminando dal set & ...) –

5

Disponibile dal Redis v2.6 è la capacità più impressionante di eseguire script Lua sul server Redis. Questo rende la sfida di riassumere i punteggi di un Ordinati Set per banale:

local sum=0 
local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES') 

for i=2, #z, 2 do 
    sum=sum+z[i] 
end 

return sum 

Runtime esempio:

~$ redis-cli zadd z 1 a 2 b 3 c 4 d 5 e 
(integer) 5 
~$ redis-cli eval "local sum=0 local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES') for i=2, #z, 2 do sum=sum+z[i] end return sum" 1 z 
(integer) 15 
+2

Una nota importante è che il server Redis Gli script lua-side bloccano TUTTO, che può essere un dealbreaker nella maggior parte dei casi. Fonte: http://stackoverflow.com/a/30896608/2440 – Sire

1

Ecco un piccolo script lua che mantiene il punteggio zset totale, come si va, in un contatore con la chiave postfixed con ".ss". Puoi usarlo al posto di ZADD.

local delta = 0 
for i=1,#ARGV,2 do 
    local oldScore = redis.call('zscore', KEYS[1], ARGV[i+1]) 
    if oldScore == false then 
     oldScore = 0 
    end 
    delta = delta - oldScore + ARGV[i] 
end 
local val = redis.call('zadd', KEYS[1], unpack(ARGV)) 
redis.call('INCRBY', KEYS[1]..'.ss', delta) 
+1

Questo script non dovrebbe costruire la chiave all'interno di lua ('KEYS [1] .. '.ss''), che" viola la semantica del comando EVAL come tutti i le chiavi utilizzate dallo script devono essere passate usando l'array KEYS "- https://redis.io/commands/eval – Jonathan

+0

@Jonathan hai ragione, la chiave per il punteggio totale deve essere passata anche nelle CHIAVI [] – Patrick