RedisとGoで実装するリアルタイムPUSH
View Slide
用語解説Radiotalk収録型の音声配信/聴アプリ番組ユーザーごとのラジオ番組トーク配信された音声クリップお気に入りメッセージRedisのメッセージNotificationFCMのメッセージ
なにをつくったのかクリップしている番組に投稿があったら通知するシステムトーカーリスナーリスナートークを投稿Notification
なにを解決したかったのかニアリアルタイム- 投稿後すぐに通知したい- 投稿後に対象ユーザーにできる限り同時に届けたい仕組みで事故を防止する- ☓ 気をつけて実行する ○ 仕組みで事故防止- 基本はDryRun- 重複送信/実行を防止する
システム概要API RedisワーカーGoCHANNEL投稿
なぜRedisなのか今回はストリーム処理が不要シンプルで高速なメッセージングキュー社内での実績があるPHPとGoに優秀なライブラリがある
超簡単!RedisのPublishとSubscribeSubscribeSUBSCRIBE {チャンネル名}subscription := client.Subscribe("TALK_POSTED_CHANNEL")PublishPUBLISH {チャンネル名} {メッセージ}$this->redis->publish($channel, $message);
なぜGoなのか並列実行を簡単にできるFirebaseAdminSDKがある(もちろんCloudMessagingSDKも)
Goによるワーカー1. メッセージの受信2. メッセージのパース3. メッセージからNotificationに必要な情報をDBから取得4. Notification内容を作成5. FCMでNotification送信
Goでの構成Reciver InvokerSenderRepository
送信の並列処理go func(to string, title string, body string, datamap[string]string) {workersChanel <- struct{}{}// この呼び出し先が実際にNotificationを送信するinvoker.Sender.Send(to, title, body, data)<-workersChanelwg.Done()}(device.Token, title, body, data)
重複実行/送信を防ぐ工夫ワーカーはメッセージを受け取ったら問答無用で送信するただし本番環境以外はDryRunワーカーを1つであること => Subscribeが1であることSubscribeが1 => 重複実行ではない保証
実行パフォーマンス並列(秒) 直列(秒)100通 2.39 23.511000通 23.16 231.4010000通 233.37 2308.81並列実行の最大数は 10に設定
今後の展望
まとめRedisとGoで実現するリアルタイム通知数千の規模であればワーカー1つでも実用性はある規模によりますが、このシンプルな構成は実装も楽でオススメ