Redisにおけるパブリッシュ/サブスクライブの仕組み
Redisは、パブリッシュ/サブスクライブ(Pub/Sub)機能を内蔵しており、非同期で軽量なメッセージ通信を実現できます。この仕組みでは、送信側(パブリッシャー)が特定のチャンネルにデータを発行し、受信側(サブスクライバー)は対象チャンネルを監視することでリアルタイムにメッセージを受け取れます。
この通信モデルは疎結合であり、システム間の依存性を低く保ちつつ、イベント駆動型の処理を構築できるため、チャットアプリや通知機能など、即時性が求められるユースケースに向いています。
基本的なコマンドと動作
RedisのPub/Subは主に以下のコマンドで構成されます:
PUBLISH チャンネル名 メッセージ:指定したチャンネルにメッセージを送信します。SUBSCRIBE チャンネル名:一つ以上のチャンネルを購読し、届いたメッセージをリアルタイムで受信します。
この方式は、メッセージキューとは異なり、永続化や再配信機能を持たない一時的かつ瞬時な通信です。接続中のサブスクライバーに対してのみメッセージが配信され、オフライン中はデータが失われます。
動作確認:CLIでのテスト手順
ローカル環境でRedisサーバーが起動している前提で、以下の手順で動作を確認できます。
1. Redisサーバーの起動
redis-server
2. サブスクライバー側の設定(別ターミナル)
redis-cli
127.0.0.1:6379> SUBSCRIBE news_feed
3. パブリッシャーからメッセージ送信
redis-cli
127.0.0.1:6379> PUBLISH news_feed "Stock price updated: $150"
上記の操作により、サブスクライバー側のコンソールに即座にメッセージが表示されます。
Pythonを使った実装例
以下は、redis-pyライブラリを使用して、バックグラウンドスレッドでメッセージを監視するサンプルコードです。
メッセージ送信側(Publisher)
import redis
# Redis接続
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
# チャンネルにメッセージを発行
channel = 'alerts'
payload = 'System overload detected!'
r.publish(channel, payload)
print(f"Sent: {payload}")
メッセージ受信側(Subscriber)
import redis
def process_alert(message):
data = message['data'].decode('utf-8')
print(f"⚠️ Alert received: {data}")
# Redis接続と購読設定
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
ps = r.pubsub()
ps.subscribe(**{'alerts': process_alert})
# 別スレッドで待機開始
print("Waiting for alerts...")
listener = ps.run_in_thread(sleep_time=0.01)
# Ctrl+Cで終了(実際の運用では適切にハンドリング)
try:
listener.join()
except KeyboardInterrupt:
listener.stop()
典型的な活用シーン
- リアルタイム通知:ユーザー宛ての通知(新着コメント、注文確定など)をクライアントに即時配信。
- イベント駆動型処理:ログ収集や監視システム内で、障害検出などのイベントを他サービスに通知。
- データ同期トリガー:在庫変更や価格更新といったイベントを複数マイクロサービスに瞬時に伝播。
- ブロードキャスト通信:負荷状況やステータス変化をクラスタ内の全ノードに同時通知。
制限事項と留意点
- メッセージの永続化なし:Redisはメッセージを保存しないため、購読者が接続していないタイミングのメッセージは失われる。
- 配信保証なし:ネットワーク断やプロセス停止時にメッセージが欠落する可能性がある。
- 高頻度発行時の負荷:大量のメッセージを短時間に送信すると、RedisインスタンスのCPUやネットワーク帯域に影響が出る。
- 代替手段の検討:信頼性や履歴管理が必要な場合は、KafkaやRabbitMQとの併用を推奨。
したがって、RedisのPub/Subは「速さ」「シンプルさ」を重視するシナリオに最適ですが、トランザクション処理や厳密なメッセージ保証が必要なシステムには不向きです。