facebookの上に出てくるようなお知らせ機能を作成するために、
redisを用いて実装をしてみたのでメモ。
お知らせ機能の作成方法、redis-objectsの使い方の参考になれば。
プッシュ機能の実装ではないのでご注意を。
詳しいAPIの利用方法はGithubで。
環境
- Ruby 2.0.0
- Ruby on Rails 4.0.2
- Redis 2.8.9
- redis(gem) 3.0.7
- redis-objects 0.9.1
要求
まず前提として要求の確認をしておきます。
- 未読お知らせ件数は日をまたいだ全てのものをカウント
- お知らせの内容、未読既読は日毎に管理
redis-objectsのインストール
以下の行を追加してbundle install
gem 'redis-objects'
redis-objectsの使い方
redis-objectsには
- モデルにインクルードする方法
- モデルと独立して利用する方法
の2通りがあります(Githubより)。
1のモデルにインクルードする方法では
モデル名:id:フィールド名
の形式でRedisのキーが作成されます。
2では独自の形式のキーが作成可能です。
実装
未読お知らせ件数と、未読既読管理についてそれぞれ実装方法をまとめます。
未読お知らせ件数のカウント
1のモデルにインクルードする方法を用います。
class User < ActiveRecord::Base
include Redis::Objects
counter :notice_counter
end
Redis::ObjectsをインクルードするとDSLが追加されます。
counterで定義したキーはRedisのString型を用いて、整数値のデータが保存されます。
上記の例ではusernotice_counterというString型のキーが作成されます。
@user = User.find(1)
@user.notice_counter.incr # お知らせに追加があったとき
@user.notice_counter.decr # お知らせがpopされたとき
@user.notice_counter.reset # すべてのお知らせを消去したとき
日毎の未読既読管理
2の独立した方法を利用します。
キーを独自に定義できるので
user:id:notice:date(yymmdd)
形式で作成します。
データ型にはリストを用います。
このキーに追加する値はモデル名:idの形式で保存します。
例) comment:10
class User < ActiveRecord::Base
def push_notice(object, date)
l = Redis::List.new(notice_key(date))
l << "#{object.class.to_s.underscore}:#{object.id}"
notice_counter.incr
end
def pop_notice(date)
l = Redis::List.new(notice_key(date))
res = l.pop
notice_counter.decr unless res
res
end
private
def notice_key(date)
"user:#{self.id}:notice:#{date.strftime('%y%m%d')}"
end
end
(例外処理などは省きました)
これで日毎の通知の未読既読の管理が可能になりました。
まとめ
以下のことについてまとめました。
- redis-objectsのインストール方法
- redis-objectsの使い方2通り
- お知らせ機能の実装
RedisはAPIがわかりやすくて使っていて気持ちいいですね。
KVS一般に言えることですが、キーの設計をちゃんと行わないと収集がつかなくなってしまうのでredis-objectsのように予め使い方をしぼってくれるのは嬉しいですね。