Dan Tang
Dan Tang

Reputation: 1343

Filtering on a category for leaderboards in Redis

I'm using Redis and sorted sets to create a leaderboard for a game, and have managed to get a basic version working. I'm wondering if it's possible to further filter on categories? For instance, let's say I am tracking the scores of users globally, and each user has a country field designating where they are from.

Is it possible to do a filter where I want to pull out the top 10 users from a particular country (rather than the whole database)?

Upvotes: 0

Views: 798

Answers (1)

Ersoy
Ersoy

Reputation: 9594

Yes it is possible but it will increase both application layer complexity and data level storage to accomplish it. Since Redis is a key/value store - querying on multiple conditions(country, game level, gender, daily/weekly/monthly top users) is a sign of you may need another solution for this problem. When you need to query multiple fields you keep denormalize your data to comfort the requirements of the business. Redis is not one of the best solutions for these kind of problems.

Cassandra(wide column store, NoSQL database) or PostgreSQL(RDBMs) would be a solution to consider at this phase. You may keep writing/updating to Postgres and cache your results in Redis for a given time.

If you want to implement this in Redis; You need to use country locales as part of the key.

You will have users key to track of users globally and you will have keys like users:it, users:es etc. to track them according to their country. Whenever you set/update the user you need to set/update them in the set of user's country.

127.0.0.1:6379> zadd users 15 a
(integer) 1
127.0.0.1:6379> zadd users:it 15 a
(integer) 1
127.0.0.1:6379> zadd users 23 b 34 c
(integer) 2
127.0.0.1:6379> zadd users:es 23 b 34 c
(integer) 2
127.0.0.1:6379> zrevrange users 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> zrevrange users 0 -1 withscores
1) "c"
2) "34"
3) "b"
4) "23"
5) "a"
6) "15"
127.0.0.1:6379> zrevrange users:it 0 -1 withscores
1) "a"
2) "15"
127.0.0.1:6379> zrevrange users:es 0 -1 withscores
1) "c"
2) "34"
3) "b"
4) "23"
127.0.0.1:6379> zadd users 45 b
(integer) 0
127.0.0.1:6379> zadd users:es 45 b
(integer) 0
127.0.0.1:6379> zrevrange users:es 0 -1 withscores
1) "b"
2) "45"
3) "c"
4) "34"
127.0.0.1:6379> zrevrange users 0 -1 withscores
1) "b"
2) "45"
3) "c"
4) "34"
5) "a"
6) "15"
127.0.0.1:6379>

One of the problems with that kind of solution is that when you need another criteria to list users, you need to migrate all of the existing users to the new system, your data size will increase significantly.

Upvotes: 3

Related Questions