読者です 読者をやめる 読者になる 読者になる

[Redis]Redisで作る更新通知

facebookの地球(?)のアイコンを押した時に表示されるようなものをイメージ。
自分の投稿に対して、いいねがついたことを通知する。

※コード書くのがめんどうだったので、redisのコマンドで記述してあります。

前提条件・要件

  • 元となるデータ(投稿、ユーザ、いいね)はRDBに管理されている
  • 新着件数、新着一覧を表示できる(ソート順は更新日時の降順)
  • 保持できる上限件数を99件とする(Redisのデータ容量を見積もることが可能)
  • 1つの投稿に対して、複数人のアクションをまとめて表示できる(○○さん他X人に・・・のような)

登録処理

  • user_id = 123の、

article_id = 234に、
user_id = 345が
2013/01/01 00:00:00(1356966000)にいいねを押したとき
→まず、既に存在しているかを確認する

HGET like:values:123 234

→emptyが返ってくるので、JSON文字列("{\"user_ids\":[345]}")を作成し、下記を実行

ZADD like:keys:123 1356966000 234
HSET like:values:123 234 "{\"user_ids\":[345]}"
ZADD like:new:123 1356966000 234
  • 同じ投稿に、

user_id = 456が、
2013/01/01 00:00:20(1356966020)にいいねを押したとき
→まず、存在確認

HGET like:values:123 234

→さっきのJSONが返却されるので、パースし、今回のuser_id(456)を追加する。
→そして、下記のコマンドを実行

ZADD like:keys:123 1356966020 234
HSET like:values:123 234 "{\"user_ids\":[345,456]}"
ZADD like:new:123 1356966020 234

同じユーザの、
article_id = 235に、
user_id = 345が
2013/01/01 00:00:40(1356966040)にいいねを押したとき
→まず、存在確認

HGET like:values:123 235

→emptyが返ってくるので、JSON文字列("{\"user_ids\":[345]}")を作成し、下記を実行

ZADD like:keys:123 1356966040 235
HSET like:values:123 235 "{\"user_ids\":[345]}"
ZADD like:new:123 1356966040 235

参照処理

  • 新着の件数を取得する(user_id=123)
ZCARD like:new:123
  • 更新通知を10件表示する(user_id=123)

→まず、キー一覧を取得する

ZREVRANGE like:keys:123 0 9

→取得できたキー(235, 234)について、値を取得する

HGET like:values:123 235
HGET like:values:123 234

RDBより、投稿・ユーザの情報を取得する

SELECT * FROM article WHERE id = 235;
SELECT * FROM user WHERE id = 456;
などなど
  • 新着更新通知を10件表示する(user_id=123)

→取得するキーが keys -> new を変えて、更新通知を10件表示するを実行する。

追記が必要なこと

  • 上限件数を越えようとした場合

ざっくり書くと、下記のような感じ。

    • 100件目以降のkeysを取得(WITHSCORES)
    • そのkeyで、valuesを削除する
    • keysの100件目のscore以下のnewを、ZREMRANGEBYSCOREを利用して削除する

multi -> exec を利用するべきかと。

書いた後気づいた

公式にtwitter cloneのcase studyがあった。
こっちを見たほうがいいんじゃなかろうか。
http://redis.io/topics/twitter-clone