Redis StreamsのXREADGROUPで発生する「NOGROUP No such consumer group」エラーの解決方法

intermediate🔴 Redis2026-05-02| Redisバージョン 5.0以上 (Linux、Docker、または AWS ElastiCache などのマネージド Redis インスタンス)

Error Message

NOGROUP No such consumer group 'mygroup' for key name 'mystream'
#redis#ストリーム#コンシューマーグループ#xreadgroup#xadd

TL;DR: クイック修正

NOGROUPエラーが発生している場合、まだ作成されていないコンシューマーグループから読み取ろうとしていることを意味します。Redisは、XREADGROUPを呼び出した際にコンシューマーグループを自動的に作成しません。

Redis CLIで以下のコマンドを実行して、ストリームとグループを同時に作成してください:

XGROUP CREATE mystream mygroup $ MKSTREAM
  • mystream: ストリームの名前です。
  • mygroup: 作成したいコンシューマーグループの名前です。
  • $: これ以降に到着する新しいメッセージのみを読み取るようRedisに指示します(最初から読み取る場合は0を使用します)。
  • MKSTREAM: ストリームがまだ存在しない場合に作成する、オプションですが強く推奨されるフラグです。

根本原因

Redis Streamsを扱う際、データの読み取りには2つの方法があります。XREAD(シンプル、ステートレス)とXREADGROUP(管理型、ステートフル)です。XREADとは異なり、XREADGROUPはどのメッセージが配信され、確認(acknowledge)されたかを追跡するために**コンシューマーグループ(Consumer Group)**を必要とします。

NOGROUP No such consumer group 'mygroup' for key name 'mystream'エラーは、コンシューマーが参加しようとする前に、Redisがグループの明示的な定義を期待しているために発生します。アプリケーションコードがXGROUP CREATEコマンドを正常に実行する前にXREADGROUPを実行しようとすると、操作は失敗します。

このエラーにつながる一般的なシナリオ:

  • ストリームは存在するが、グループが作成されていなかった。
  • ストリームが削除または期限切れになり、コンシューマーグループのメタデータも一緒に消えた。
  • アプリケーションのデプロイスクリプトで初期化ステップが漏れていた。
  • 移行やフラッシュの後など、グループが存在しない新しいRedisデータベースを指している。

ステップバイステップの修正方法

1. Redis CLIによる手動作成

ローカル環境やステージング環境でデバッグしている場合、最も早い方法はグループを手動で作成することです。インスタンスに接続して以下を実行します:

# ストリーム 'mystream' に対してグループ 'mygroup' を作成
# '$' はストリームの最後から読み取りを開始することを意味します
XGROUP CREATE mystream mygroup $

ストリーム自体がまだ存在しない場合、上記のコマンドはERR no such keyで失敗します。両方を一度に処理するには、Redis 6.2で導入されたMKSTREAMサブコマンドを使用します:

XGROUP CREATE mystream mygroup $ MKSTREAM

2. プログラムによる実装(冪等なセットアップ)

本番環境では、アプリケーションコード内でこれを処理する必要があります。複数のワーカーが同時に起動する可能性があるため、別のワーカーによって既に作成されている場合にクラッシュすることなく、グループが確実に存在するようにする方法が必要です。

以下は、try-catchブロックを使用した一般的なパターンです(Python/redis-pyの例):

import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)
stream_name = "mystream"
group_name = "mygroup"

try:
    # グループの作成を試行
    r.xgroup_create(stream_name, group_name, id="$", mkstream=True)
except redis.exceptions.ResponseError as e:
    if "BUSYGROUP" in str(e):
        print("Group already exists, skipping creation.")
    else:
        raise e

# これで安全に読み取り可能
messages = r.xreadgroup(group_name, "consumer-1", {stream_name: ">"})

BUSYGROUPエラーをキャッチすることで、コードは冪等(べきとう)になり、複数回安全に実行できるようになります。

修正の確認

コンシューマーグループが正しく設定されているか確認するには、XINFOコマンドを使用します。これはストリームのメタデータを検査するための標準的な方法です。

特定のストリームのすべてのグループを確認します:

XINFO GROUPS mystream

以下のような出力が表示されるはずです:

1) 1) "name"
   2) "mygroup"
   3) "consumers"
   4) (integer) 1
   5) "pending"
   6) (integer) 0
   7) "last-delivered-id"
   8) "1714550000000-0"

リストが空であるか、グループ名が見当たらない場合、XREADGROUPコマンドは引き続き失敗します。

避けるべき一般的な落とし穴

  • 大文字と小文字の区別: Redisのキーとグループ名は、大文字と小文字を区別します。'MyGroup' は 'mygroup' とは異なります。
  • データベースインデックス: 複数のデータベース(例:SELECT 1)を使用している場合は、作成コマンドと読み取りコマンドが同じデータベースインデックスをターゲットにしていることを確認してください。
  • ストリームの削除: DEL mystreamを使用すると、ストリームおよび関連するすべてのコンシューマーグループが削除されます。データをクリアしつつグループを保持する必要がある場合は、代わりにXTRIMまたはXDELを使用してください。

参考文献

Related Error Notes