Redis Pub/Subの深淵:その「気軽さ」の裏にあるアーキテクチャの代償を見極めろ
Redisを単なるキャッシュストアだと思っているなら、それは大きな誤解だ。Pub/Sub(Publish/Subscribe)機能は、システム間の疎結合を実現する強力な武器だが、同時に「銀の弾丸ではない」ということを理解しなければならない。
今日は、Redis Pub/Subを実戦投入するエンジニアのために、ドキュメントの表面をなぞるだけでは決して辿り着けない「本質的な設計指針」を授ける。
—
1. Pub/Subのアーキテクチャ:なぜ「高速」なのか?
RedisのPub/Subは、「火を放って忘れる(Fire and Forget)」という哲学で動いている。
- 永続化されない: Redisはメッセージをメモリに保持しない。送った瞬間に受信者がいなければ、そのメッセージは宇宙の彼方へ消え去る。
- O(1)の驚異: 購読者リストをメモリ上のハッシュテーブルで管理しているため、`PUBLISH`のコストは購読者数に比例するのみ。極めて低レイテンシだ。
この「軽さ」こそが最大の利点だが、実務において最も危険な罠でもある。
—
2. 実践的コマンド運用と設計の注意点
基本的なコマンドは誰でも使える。重要なのは、「いつ使い、いつ使うべきではないか」の判断基準だ。
基本コード例
クライアントA: 購読開始(ブロッキングされる)
SUBSCRIBE news.tech
-> 1) “subscribe” 2) “news.tech” 3) 1
クライアントB: メッセージ送信
PUBLISH news.tech “Redis Internals are beautiful”
-> (整数値: 購読者数) 1
現場で絶対に守るべき鉄則
1. 「確実な到達」を求めてはならない: ネットワーク切断やクライアントのクラッシュでメッセージは消失する。決済や重要ログの配送にPub/Subを使ってはいけない。その場合は迷わず `Redis Streams` を採用すべきだ。
2. クライアントのバッファオーバーフロー: 受信側が遅い場合、Redisの出力バッファが肥大化し、最悪の場合、Redisプロセスが強制終了(OOM Killer)する。`client-output-buffer-limit pubsub` の設定値は、システムのスループットに合わせて必ずチューニングせよ。
—
3. 堅牢な設計パターン:疎結合を保つための工夫
Pub/Subを使う際、アプリケーションコードに直接 `SUBSCRIBE` を書くのは避けろ。責務を分離するのだ。
推奨:メッセージングゲートウェイパターンの導入
Pub/Subのクライアントを独立したプロセス(またはスレッド)として切り出せ。
- 理由: アプリ本体の再起動やエラーハンドリングにPub/Subが引きずられないようにするため。
- 構成:
- Producer: Redisへ `PUBLISH` するだけ。
- Gateway: `SUBSCRIBE` を専任し、受け取ったメッセージを内部キューやWebHook、あるいはWebSocketで各ワーカーへルーティングする。
—
4. 高度な監視:PUBSUBコマンドの活用
運用中、「誰が何を聞いているのか」が見えなくなるのがPub/Subの怖さだ。`PUBSUB` サブコマンドを使いこなせ。
現在購読されているチャンネルを表示
PUBSUB CHANNELS
-> 1) “news.tech”
特定チャンネルの購読者数を確認
PUBSUB NUMSUB news.tech
-> 1) “news.tech” 2) 5
チーフアーキテクトからの助言:
本番環境では、`PUBSUB` を使って購読者数をメトリクスとして収集し、Grafanaなどで可視化せよ。「なぜかメッセージが届かない」という原因の多くは、クライアントが意図せず切断されていたことによるものだ。
—
結論:Redis Pub/Subをどう使いこなすべきか
Redis Pub/Subは、「リアルタイム性が重要で、かつデータの欠損がある程度許容される通知機能」に最適化されている。
- 通知系: チャットのオンラインステータス、UIのリアルタイム更新、設定変更の通知。
- 避けるべき: 業務トランザクション、順序保証が必要なキューイング、メッセージの永続化が必要な処理。
もし「あと少しの信頼性」が必要なら、Redis Streamsへ移行せよ。それがエンジニアとしての賢明な判断だ。
アーキテクチャの決定に「なんとなく」は許されない。Pub/Subの特性を骨の髄まで理解し、システムにとって最適な選択をせよ。コードは嘘をつかないが、設計の甘さは必ず後から牙を剥く。
健闘を祈る。
コメント