13

I'm using Redis sorted set to implement the leaderboard of my game, where I show the user ranking in descending order. I'm stuck in a case where two or more users have the same score. So in this case, I want the higher ranking of the user who gets the score first. For example, I'm adding the following entries in Redis.

127.0.0.1:6379> zadd testing-key 5 a
(integer) 1
127.0.0.1:6379> zadd testing-key 4 b
(integer) 1
127.0.0.1:6379> zadd testing-key 5 c
(integer) 1

and when I'm querying for the rank in reverse order, I'm getting this

127.0.0.1:6379> zrevrange testing-key 0 10
1) "c"
2) "a"
3) "b"

but in my case, the ranking should be like

1) "a"
2) "c"
3) "b"

So is there any provision in Redis to give higher precedence to the entity which entered first in the set with the same score?

ankit.vishen
  • 920
  • 10
  • 26

2 Answers2

11

If your leaderboard's scores are "small" enough, you may get away with using a combination of the score and the timestamp (e.g. 123.111455234, where 123 is the score). However, since the Sorted Set score is a double floating point, you may lose precision.

Alternatively, keep two Sorted Sets - one with each player's leaderboard score and the other with each player's score timestamp, and use both to determine the order.

Or, use a single sorted set for the leader board, encode the timestamp as part of the member and rely on lexicographical ordering.

Itamar Haber
  • 39,899
  • 5
  • 67
  • 94
11

I found out one solution to this problem. In my case, the score is an integer so I converted it into decimal and added Long.MAX_VALUE - System.nanoTime() after decimal. So the final score code looks like

double finalScore = score.(Long.MAX_VALUE - System.nanoTime());

So the final score of the player who scored first would be higher than the second one. Please let me know if you have any better solution.

ankit.vishen
  • 920
  • 10
  • 26
  • 2
    But isn't that what I (perhaps tersely and succinctly, but hopefully not inaccurately and certainly with only the of best intentions intended) answered in my first paragraph? – Itamar Haber Oct 30 '18 at 17:40
  • 1
    Only appending timestamp with score will not produce the desired result if we call `zrevrange`(In my case). Because timestamp field should be descending order to give high ranking to the user who scored first, so the final score should be `mainScore.(Some max value - System.nanoTime())` – ankit.vishen Oct 31 '18 at 05:57