Skip to main content

Groups

A consumer group reads a stream with one cursor and keeps every entry it delivered and nobody acknowledged in its pending entries list.

One consumer group over a stream: its cursor, its pending entries list, and the commands that move entries between themStream orders, as group workers sees it1-0acked2-0acked3-0pending4-0pending5-0new6-0newCursor:last-delivered-idPending entries list:3-0 to c1, 4-0 to c2Consumer c1reads new entriesConsumer c2acknowledgesConsumer c3claims idle onesXGROUP SETID moves the cursor back or forward: a seek
The diagram as text
  1. Stream orders, as group workers sees it: 1-0 acked; 2-0 acked; 3-0 pending; 4-0 pending; 5-0 new; 6-0 new
  2. Cursor: last-delivered-id → 4-0 pending: points at
  3. Consumer c1 reads new entries → Cursor: last-delivered-id: XREADGROUP
  4. Consumer c2 acknowledges → Pending entries list: 3-0 to c1, 4-0 to c2: XACK
  5. Consumer c3 claims idle ones → Pending entries list: 3-0 to c1, 4-0 to c2: claim
  6. XGROUP SETID moves the cursor back or forward: a seek

XREADGROUP with the id > returns the entries past the group's cursor, its last-delivered-id, and moves the cursor. Each entry goes to the one consumer that read it. The group records the entry in its pending entries list (PEL) with that consumer, the time of the delivery and a delivery count. XACK removes it from the list. The entry stays in the stream: an acknowledgement is the group's bookkeeping, not a delete.

The crate creates the group when the subscription starts, with XGROUP CREATE and MKSTREAM, so a stream that does not exist yet is created empty. A group that already exists is kept as it is. StreamStart decides where a new group's cursor starts.

An entry whose consumer died stays in the list. Two commands hand it to another consumer once it has been idle for a given time. XAUTOCLAIM scans the list for such entries and transfers them; RedisStream::reclaim reads that way, and asks XPENDING for the delivery counts of what it claimed. On Redis 8.4 and later XREADGROUP takes a CLAIM option, which returns the idle entries first and then new ones in one call, each with its idle time and delivery count. RedisStream::claiming reads that way, and a claiming subscription refuses to start on an older server.

XGROUP SETID moves the cursor. The crate's RedisGroupSeeker uses it, so a seek repositions the whole group, not one consumer. A read that was selected under the old cursor is discarded, and the next read starts from the new one.

The commands are Redis's own: XREADGROUP, XACK, XAUTOCLAIM and XGROUP SETID.