phpredisでデイリーランキング
redisのソート済みセット型を使えば簡単にランキングが実装できるらしい
勉強がてらやってみた
phpredisのセットアップはこっちを参考に
環境
- redis 3.0.7
- php 7.0.3
- phpredis
やること
- JSONで日付、ユーザーID、スコアを受け取る
- 例 {"date":"2016-02-28","id":2,"score":999}
- JSONで順位、参加人数を返却
- 例 {"rank":200,"total":10000}
いざ!
Ranking.php
<?php $json = file_get_contents('php://input'); $obj = json_decode( $json ); $date = $obj->{'date'}; $id = $obj->{'id'}; $score = $obj->{'score'}; /*バリデーションは割愛*/ //Redisへ接続 $redis = new Redis(); $redis->connect("127.0.0.1",6379); //ユーザー追加&ランキング更新(日付をKeyにする) $redis->zAdd($date,$score,$id); //該当日の要素数取得 $total = $redis->zCard($date); //スコアを降順に並べて、自分の順位を取得 $rank = $redis->zRevRank($date, $id); //0番目から順に順位が振られるのでインクリメント $rank++; //結果をJSONで返却 header('Content-type: application/json'); echo json_encode(array('rank'=>$rank,'total'=>$total));
テスト
idやscoreを変えながらJSONをPOSTしてみる
$ curl -H "Content-type: application/json" -X POST -d '{"date":"2016-02-28","id":1,"score":100}' http://localhost/Ranking.php {"rank":1,"total":1} $ curl -H "Content-type: application/json" -X POST -d '{"date":"2016-02-28","id":2,"score":1000}' http://localhost/Ranking.php {"rank":1,"total":2} $ curl -H "Content-type: application/json" -X POST -d '{"date":"2016-02-28","id":3,"score":10}' http://localhost/Ranking.php {"rank":3,"total":3} $ curl -H "Content-type: application/json" -X POST -d '{"date":"2016-02-28","id":1,"score":1001}' http://localhost/Ranking.php {"rank":1,"total":3}
とりあえず問題なさそう
懸念点
同点ユーザーがいた場合に同じ順位とならないので、同着を取りたければ一手間加える必要がある
自分より高いスコアのユーザー数を抽出して+1するのが一般的??