
どうも、プラットフォームDivでエンジニアをやっている Wataru です。
最近3人目の子供が産まれて、産後自宅勤務をさせてくれた弊社はとてもいい会社だと思います。出産予定のあるエンジニアのかたは是非弊社に転職を。
さて、今回はRedisの紹介をさせて頂きたいと思います。
Redisってすごくマイナーなわけではないのですが、めちゃくちゃ便利なのにあまり注目されていないなーという印象があるので、これを機会に是非使ってみてもらえると嬉しいです。
Redisって何?
Redisとは「remote dictionary server」から名前が付けられたオープンソースのkey-valueデータストアです。MemcacheDB等のKVSとの最大の違いは、格納するバリューがデータ構造というところです。
つまり、リスト・セット・ハッシュなどのデータ構造で格納できるのでバリューに対してアトミックな操作ができます。
例えば、リストではプッシュしたりポップしたりできるのです。
これによって大規模なデータの操作をする時にデータ構造だけプログラムの外部で管理する事ができるので大変便利です。
RedisはANSI Cで書かれていて、すべてのデータセットをメモリ内に読み込むため、危険なほどのスピードで動作するというのが売りです。
Salvatore Sanfilippo 氏によって開発されていてスポンサーにはVMwareがついています。
またリリースも頻繁に行われていて、そういった意味でも安心感のあるプロダクトとなっています。
Redisをランキング生成に使ってみてはどうだろう
データ構造を操作できるRedisの使い道は、ページビューの集計とか傾向分析とか色々と考えられますが、今回はRedisのデータ構造の中でも「ソート済みセット型」というのを使って、リアルタイムランキングを生成する方法を考えてみたいと思います。リアルタイムランキングは、参照したタイミングで自分の順位を取得するわけですが、同率も考慮しなければいけないので下記のような手順で算出します。
①自分のポイントを取得
②自分のポイントより高得点のユーザー数をカウント
③それを+1したものが自分の順位
実際にRedisのコマンドではこんな感じになります。
redis 127.0.0.1:6379> zscore rank ${userのid}redis 127.0.0.1:6379> zcount rank (${上で取得したscore} +inf
これで取得したrank+1が順位になります。
MySQLで同じ事をする場合のSQLはこんな感じですね。
SELECT count(id)+1 FROM ranking WHERE point < (SELECT point FROM ranking WHERE id=${userのid})
KVSなのにこんな事できるなんてすごい!!
Redis、なにそれ美味しいの?
という訳で一応MySQLと比較してみました。MySQLはメモリーエンジンを使っています。
DDLはこんな感じです。
drop table if exists ranking;create table ranking( id VARCHAR(12) NOT NULL PRIMARY KEY, point BIGINT NOT NULL, INDEX USING HASH (point)) ENGINE=MEMORY;
検証に使ったソースはGitHubにあげてありますので、そちらを参照していただければと思います。
https://github.com/wataru420/redisTest
検証環境
サーバ | Dell PowerEdge R300 |
OS | CentOS release 5.4 (Final) |
CPU | Intel(R) Core(TM)2 Duo CPU E6405 @ 2.13GHz ×2 |
Memory | 12G |
MySQL | 5.5.15 |
Redis | 2.4.1 |
Java | 1.6.0 29 |
scala | 2.9.1 |
比較結果は下記の通り。
Redis | MySQL | |
---|---|---|
1回目 | 10581ms | 12080ms |
2回目 | 10658ms | 12061ms |
3回目 | 10519ms | 12171ms |
4回目 | 10791ms | 12054ms |
5回目 | 10571ms | 11793ms |
6回目 | 10590ms | 12473ms |
7回目 | 10890ms | 11937ms |
8回目 | 10524ms | 12008ms |
9回目 | 10658ms | 12017ms |
10回目 | 10495ms | 11919ms |
平均 | 10628ms | 12051ms |
Redis | MySQL | |
---|---|---|
1回目 | 480254ms | 910331ms |
2回目 | 480016ms | 918647ms |
3回目 | 478447ms | 918561ms |
4回目 | 480574ms | 910602ms |
5回目 | 478681ms | 917728ms |
6回目 | 479560ms | 916124ms |
7回目 | 480081ms | 909503ms |
8回目 | 480529ms | 917050ms |
9回目 | 479809ms | 917383ms |
10回目 | 478096ms | 909949ms |
平均 | 479605ms | 914588ms |
書き込みは若干、読み取りは圧倒的にRedisの方が早いという結果になりました。
Redisは書き込み時に順序付けした状態で書き込んでいるので読み取りが高速になるのかと思います。
まとめ
ランキングは昨今のソーシャルアプリには無くてはならない要素になっています。またランキング以外にもオンメモリーで処理をしたいようなデータを扱う際はRedisはとても有効だと思います。
この記事を読んでRedis使ってみたいなと思って頂けたら幸いです。
是非みなさんも危険なほどのスピードを体験してみてください。
参考文献
- redis公式サイト
- http://redis.io/
- redisドキュメント日本語訳
- http://redis.shibu.jp/index.html
- redisのgithubレポジトリー
- https://github.com/antirez/redis