Slide 1

Slide 1 text

RedisとGoで実装する リアルタイムPUSH

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

用語解説 Radiotalk 収録型の音声配信/聴アプリ 番組 ユーザーごとのラジオ番組 トーク 配信された音声 クリップ お気に入り メッセージ Redisのメッセージ Notification FCMのメッセージ

Slide 4

Slide 4 text

なにをつくったのか クリップしている番組に投稿があったら通知するシステム トーカー リスナー リスナー トークを投稿 Notification

Slide 5

Slide 5 text

なにを解決したかったのか ニアリアルタイム - 投稿後すぐに通知したい - 投稿後に対象ユーザーにできる限り同時に届けたい 仕組みで事故を防止する - ☓ 気をつけて実行する ○ 仕組みで事故防止 - 基本はDryRun - 重複送信/実行を防止する

Slide 6

Slide 6 text

システム概要 API Redis ワーカー Go CHAN NEL 投稿

Slide 7

Slide 7 text

なぜRedisなのか 今回はストリーム処理が不要 シンプルで高速なメッセージングキュー 社内での実績がある PHPとGoに優秀なライブラリがある

Slide 8

Slide 8 text

超簡単!RedisのPublishとSubscribe Subscribe SUBSCRIBE {チャンネル名} subscription := client.Subscribe("TALK_POSTED_CHANNEL") Publish PUBLISH {チャンネル名} {メッセージ} $this->redis->publish($channel, $message);

Slide 9

Slide 9 text

なぜGoなのか 並列実行を簡単にできる FirebaseAdminSDKがある(もちろんCloudMessagingSDKも)

Slide 10

Slide 10 text

Goによるワーカー 1. メッセージの受信 2. メッセージのパース 3. メッセージからNotificationに必要な情報をDBから取得 4. Notification内容を作成 5. FCMでNotification送信

Slide 11

Slide 11 text

Goでの構成 Reciver Invoker Sender Repository

Slide 12

Slide 12 text

送信の並列処理 go func(to string, title string, body string, data map[string]string) { workersChanel <- struct{}{} // この呼び出し先が実際にNotificationを送信する invoker.Sender.Send(to, title, body, data) <-workersChanel wg.Done() }(device.Token, title, body, data)

Slide 13

Slide 13 text

重複実行/送信を防ぐ工夫 ワーカーはメッセージを受け取ったら問答無用で送信する ただし本番環境以外はDryRun ワーカーを1つであること => Subscribeが1であること Subscribeが1 => 重複実行ではない保証

Slide 14

Slide 14 text

実行パフォーマンス 並列(秒) 直列(秒) 100通 2.39 23.51 1000通 23.16 231.40 10000通 233.37 2308.81 並列実行の最大数は 10に設定

Slide 15

Slide 15 text

今後の展望

Slide 16

Slide 16 text

まとめ RedisとGoで実現するリアルタイム通知 数千の規模であればワーカー1つでも実用性はある 規模によりますが、このシンプルな構成は実装も楽でオススメ