redis-objectsで簡単なリアルタイムランキングの実装
rubyのgemにredis-objectsというredisのヘルパーgemがある。
今回、redisを使用して簡易なリアルタイムランキングを実装する機会があったのだけど、とても簡単にできたのでメモしておく。実用的ではないかもしれないが個人のシステムレベルなら使えるかもしれない。
さて、わかりやすくするために今回は記事のリアルタイムアクセスランキングを実装する場合を例にとる。
流れはこう。
- Redisのsorted setを利用。
- 記事へのアクセスごと、記事IDをkeyにしてそのscoreをインクリメントする。
これだけ。
実装は以下のような感じ。ホストのセットは公式のREADMEに則った。
Gemfile
gem 'redis-objects'
initializers/redis.rb
Redis::Objects.redis = Redis.new(:host => '127.0.0.1', :port => 6379)
Article.rb
class Article < ActiveRecord::Base include Redis::Objects sorted_set :ranking # 記事IDごとのスコアをインクリメント def self.increase_rank_score(article_id) article = Article.find(1) # イケてない article.ranking.incr(article_id, 1) end # 上位1~5位の記事IDを取得 def self.get_ranking article = Article.find(1) # イケてない return article.ranking.members.reverse.slice(0,5) end end
articles_controller.rb
class ArticlesController < ApplicationController def show Article.increase_rank_score(params[:id]) @article = Article.find(params[:id]) end end
rankings_controller.rb
class RankingsController < ApplicationController def show @ranks = Article.get_ranking end end
Article.rbでは記事へアクセスがあるたびにスコアをインクリメントするメソッドと上位1~5位の記事IDを取得するメソッドを定義。
いちいちオブジェクトを介さないといけないのがイケてない。とりあえずは記事IDを1で代替してる。
articleコントローラでは記事アクセスのたびにincrease_rank_scoreを呼び出す。
rankingコントローラでは上位5位のランキングで記事IDを取得。
こんな感じで実装すると記事ごとのアクセスランキングがリアルタイムで取得できる。
日毎にランキングの結果を残しておきたいという需要があれば作成したsorted setを1日おきに集計してごっそりMySQLとかにいれとけばいい。
他にも似たような仕組みでRedisのCounterを使うと、アクセスカウンタとか作れるかも。
redis便利だ。
おわり。