Reputation: 3914
I would like to use a redis' sorted set as a leader board. But using ZREVRANGE 0 x
, I can only get the top x from the score (the end of the score based ascending sorted set), with the default tie breaker which is, from the official redis documentation:
Lexicographical order is used for elements with equal score.
The tie breaker I would need is the date time of the score entry.
e.g.
submits (in order) redis sorts it as I need
User1 -- Score 50 User1 User1
User3 -- Score 40 User2 User3
User2 -- Score 40 User3 User2
The only solution I see is to store the date time of the last update on the entry but still use ZREVRANGE key 0 x
to get max and min scores from the the top x users. Then do a ZREVRANGEBYSCORE key max min
. If the result length is higher than x, there is at least one tie so I would sort that smaller list in Lua using 2 keys.
This method seems very slow and I need to make it work for hundreds of thousands of users. I don't like the 2 calls and processing with Lua (on the redis side, to stay atomic) and would like to know if there is a better way to use 2 keys for sorted sets or configure another tie breaker?
My code is already written so I cannot change my type of database. If you have any interesting idea, I am interested to hear them, as I am not an expert about redis.
Upvotes: 2
Views: 4622
Reputation: 43235
The sorted set score is a floating point value. Your score and datetime of the score can both fit into that.
Now lets call the redis score as RScore. You can put the person's score in leftmost 10 bits of the number, and timestamp in rightmost x bits. The bits in middle can be zero.
So, whenever you sort Rscore, it will be first sorted by score, and if there is a tie, it will be sorted by unix timestamp present in the right bits. To find the score and timestamp of the score from RScore, you just have to parse the right set of bits. An example utility which does this in python is here.
Upvotes: 8