Track Kafka Consumer Offsets and Replay Events

Big DataBeginner
Practice Now

Introduction

Kafka keeps records independently of who has read them. A consumer group also needs to remember its progress so a later process can continue rather than start over. A committed offset is the next position that group should read in a partition, not the last record's number.

You will read two of four prepared records, inspect committed progress and lag, resume with the same group, and compare a new group. Then you will preview and execute a reset while the original group is inactive, and read the retained records again. The topic has one partition to keep the positions easy to reason about.

This independent lab supplies the broker, four records, and a helper that polls actual coordinator state until an expected offset appears. Basic terminal use is enough; no Python coding or service setup is needed. The helper does not alter offsets or manufacture a report. Use the Terminal.

Read Two Records and Inspect the Next Committed Position

In this step, you will connect a bounded read with the group's actual saved position. Inspect the four prepared values:

cd /home/labex/project
cat /home/labex/project/data/progress-events.txt

Their offsets in this new one-partition topic are 0 through 3. A new group named orders-review has no saved position, so --from-beginning selects the retained beginning for this initial read.

--command-property passes a configuration value to the consumer client, rather than changing the event-display format. The console client automatically commits progress in this exercise. max.poll.records=1 limits each poll to one returned record so stopping after two displayed records does not advance its position through a larger returned batch. The interval sets periodic commit behavior; the closing client also finishes its normal progress handling. You will inspect the actual result rather than assume a particular delay:

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-progress --group orders-review --from-beginning --max-messages 2 --timeout-ms 30000 --command-property enable.auto.commit=true --command-property auto.commit.interval.ms=1000 --command-property max.poll.records=1 > /home/labex/project/output/first-two.txt
cat /home/labex/project/output/first-two.txt

Expect the two created events, then the client exits. Run the provided bounded polling helper with the group name and expected next offset:

/home/labex/project/tools/wait-group-offset orders-review 2 > /home/labex/project/output/after-first.txt
cat /home/labex/project/output/after-first.txt

The helper repeatedly describes the real group until its committed offset is 2, or fails after its deadline. It does not commit or reset anything. Find CURRENT-OFFSET 2, LOG-END-OFFSET 4, and LAG 2 for partition 0. A message saying the group has no active members is normal after the bounded client exits; its saved progress still exists.

Offset 2 means the next read begins with the third stored record. The end offset 4 is the next position after the four existing records; lag 4 − 2 = 2 measures the remaining records in this simple settled example. The first two records were not deleted.

Resume the Same Group and Compare a New Group

In this step, you will predict which records a group receives from its saved position. Run the same group again, keeping the beginning option deliberately:

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-progress --group orders-review --from-beginning --max-messages 2 --timeout-ms 30000 --command-property enable.auto.commit=true --command-property auto.commit.interval.ms=1000 --command-property max.poll.records=1 > /home/labex/project/output/resumed-two.txt
cat /home/labex/project/output/resumed-two.txt

Expect the two paid events, not the earlier created events. --from-beginning supplies a starting policy when no valid committed offset exists; it does not override this group's valid saved offset 2. Confirm completion through actual coordinator state:

/home/labex/project/tools/wait-group-offset orders-review 4 > /home/labex/project/output/after-resume.txt
cat /home/labex/project/output/after-resume.txt

Expect committed offset 4, end offset 4, and lag 0. Now predict a different group named orders-independent. It has no saved position and is independent of orders-review, so a beginning read should return all four retained records:

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-progress --group orders-independent --from-beginning --max-messages 4 --timeout-ms 30000 --command-property enable.auto.commit=true --command-property auto.commit.interval.ms=1000 --command-property max.poll.records=1 > /home/labex/project/output/new-group-all.txt
cat /home/labex/project/output/new-group-all.txt
/home/labex/project/tools/wait-group-offset orders-independent 4 > /home/labex/project/output/new-group-position.txt
cat /home/labex/project/output/new-group-position.txt

Expect all four values and that new group's own committed offset 4. The groups can both reach the end while having followed different reading histories. One group's progress did not move the other group's starting position, and neither group's consumption removed the topic records.

Next, you will change the original group's saved position deliberately, rather than treating the beginning option as a rewind command.

Preview an Inactive-Group Reset and Replay the History

In this step, you will reset only orders-review. Its bounded consumer has exited, so the group has no active member. Stop any accidentally left-running member of that same group before resetting; an active consumer could continue changing progress.

--reset-offsets selects the progress-management operation, --topic limits its scope, and --to-earliest selects the retained beginning. First use --dry-run to preview the proposed new offset without applying it:

kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group orders-review --reset-offsets --to-earliest --topic orders-progress --dry-run > /home/labex/project/output/reset-preview.txt
cat /home/labex/project/output/reset-preview.txt

Expect a proposed NEW-OFFSET of 0. Confirm that previewing did not change the current saved position:

/home/labex/project/tools/wait-group-offset orders-review 4 > /home/labex/project/output/after-preview.txt
cat /home/labex/project/output/after-preview.txt

Now apply that scoped reset with --execute:

kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group orders-review --reset-offsets --to-earliest --topic orders-progress --execute
/home/labex/project/tools/wait-group-offset orders-review 0 > /home/labex/project/output/after-reset.txt
cat /home/labex/project/output/after-reset.txt

The actual committed next offset should now be 0, with end offset 4 and lag 4. The records stayed in place; only this group's saved position changed. Read all four again using the now-valid committed beginning, without relying on a starting-default option:

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-progress --group orders-review --max-messages 4 --timeout-ms 30000 --command-property enable.auto.commit=true --command-property auto.commit.interval.ms=1000 --command-property max.poll.records=1 > /home/labex/project/output/replayed-all.txt
cat /home/labex/project/output/replayed-all.txt
/home/labex/project/tools/wait-group-offset orders-review 4 > /home/labex/project/output/after-replay.txt
cat /home/labex/project/output/after-replay.txt

Expect the original four values and committed offset 4 again. orders-independent should still have its own completed position; the reset did not rewind that group.

Replay intentionally reads existing records again. A crash between handling a record and committing progress can also cause a record to be delivered again. This console exercise demonstrates reading positions, not an atomic file-write-and-commit transaction or an end-to-end exactly-once guarantee. Later Python labs will make the processing and commit order explicit.

Summary

You inspected committed next offsets and lag, resumed from saved progress despite a beginning default, and compared an independent group. An inactive-group dry-run and executed reset enabled deliberate replay while the actual topic records remained unchanged. Next, you will observe how several members of one group share partitions and recover an assignment after a member leaves.