Redisでランキング実装してみませんか

初めまして
プログラマの吉行と申します。

今回はRedisのソート済みセット型について書きたいと思います。


■Redisとは
インメモリ型のKVSになります。
レプリケーションにも対応しています。

Redisで扱えるデータ構造は次のとおりです。
string - 文字列型
list - リスト型
set - セット型
hash - ハッシュ型
sorted set - ソート済みセット型

通常でも用いるデータ構造をそのままRedisで表現でき要素の追加や削除、ソートなどの操作もコマンドで用意されています。



■ソート済みセット型はどんなことが出来るか
要素を追加、変更する度にスコアで自動的にソートしてくれるので、ランキングのような機能に使用するならとても使いやすいものとなります。

バッチ処理等の集計が必要ないランキングが実装出来ます。


■ランキングの取得について
ソート済みセット型を使用すればRedisコマンドを使用するだけで順位が取得できます。
zrank(key, member) ー 昇順で順位を取得
zrevrank(key, member) ー 降順で順位を取得

ただし下記ような場合で順位を取得するとuser3=3位でuser4=4位となる。
これはRedisには同率順位が無いためである。
|index |member |score |
|1 |user1 |5      |
|2 |user2 |4     |
|3 |user3 |3     |
|4 |user4 |3     |
|5 |user5 |2     |

同率順位を考慮した場合は、自分より大きいスコアの件数を取得し+1する事で順位が求められます。
実際のRedisコマンドだとこんな感じになります。

redis 127.0.0.1:6379> zscore key member
redis 127.0.0.1:6379> zcount key 上で取得したscore +inf

取得した値に+1したのが順位となります。

zscore(key, member) ー 指定した要素のスコアを取得
xcount(key, min, max) ー スコアが min 以上 max 以下のすべての要素を取得



■ランキングを前半戦と後半戦で開催したい
ソーシャルゲームでは累計獲得ポイントで順位が決まるランキング形式のイベントが良く開催されていますが、そのイベントを前半部分と後半部分に分けたいと言った時はKeyを分ける事で簡単に対応できます。
key = 前半戦
|index |member |score |
|1 |user1 |5     |
|2 |user2 |4     |
|3 |user3 |3     |
|4 |user4 |3     |
|5 |user5 |2     |

key = 後半戦
|index |member |score |
|1 |user1 |10     |
|2 |user2 |8      |
|3 |user3 |6     |
|4 |user4 |6     |
|5 |user5 |4     |

後半戦のスコアを取得する時のRedisコマンドはこんな感じになります。

redis 127.0.0.1:6379> zscore 後半戦 user1
この場合の取得スコアは10となります。

後半戦スコアは前半戦スコアを含めてものとしたい場合は、前半戦から加算を行っていれば大丈夫です。

ランキングを実装する際にRedisを検討してみてはいかがでしょうか。

コメント