-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offset "resets" during rebalance #2782
Comments
At step 8 I guess you mean Consumer B, right? At step 9, are you calling commit() from the Assign event handler or shortly after calling Assign (but prior to receiving a new message)? You shouldn't call commit() until you've offset_store()d a new offset, but that might be tricky to handle, so your proposed workaround sounds like a better alternative. Should librdkafka automatically reset the stored offsets to INVALID when partitions are unassigned? I think this might occur with auto commits too, but it is less likely since this is technically a race condition between fetching committed offsets after assign() and the next commit, and offset fetches are typically quick. |
Great report btw! |
@mhowlett Thoughts on resetting the stored offset to INVALID on assign/unassign? |
@edenhill
At step 8 I've meant consumer A correctly. Every rebalance consists of revoke event (even if 0 partitions were assigned). You can see this in the logs I've provided too:
Yes, I'm calling commit shortly after assign (other thread, but stil,l before offsets are fetched) only to expose the situation. The workaround is currently implemented and running in our production deployment and so far we are not seeing offsets being reset anymore. To give you idea about the scale: our production environment consists of 16 instances consuming total of 3000 messages per second (on average). I've also fixed couple of other issues that greatly reduces number of rebalances occurring so we'll have to wait some more time to make any sound conclusions on this.
In our experience kafka cluster can introduce up to 10s of latency (99 percentile) in commit operations, so maybe in such conditions fetch can be slow sometimes? There is also slight possibility that the issue was actually caused by manual commit that was implemented in case of application shutdown. Invalid offsets would be commited but it's extremely unlikely. It'd require shutdown immediately after rebalance and this rebalance would need to "restore" previously assigned partitions to a consumer. Anyway, it would be great to either confirm or reject the presence of the issue in auto-commit/manual-store use case. |
Ah, right 👍
The auto commit timer will fire every commit interval regardless of the current state as long as there is a current assignment (non-empty assign()) and a commit request will be sent for all stored offsets of the assigned partitions whose offset is greater than the last known committed offset. |
…ixes #2782) This fixes the case where a manual offset-less commit() or the auto-committer would commit a stored offset from a previous assignment before a new message was consumed by the application.
…ixes #2782) This fixes the case where a manual offset-less commit() or the auto-committer would commit a stored offset from a previous assignment before a new message was consumed by the application.
…ixes #2782) This fixes the case where a manual offset-less commit() or the auto-committer would commit a stored offset from a previous assignment before a new message was consumed by the application.
We may have observed this behavior (or something very similar) with a confluent-kafka-python (pinned to v1.5.0) client that manually stores offsets in the offset store and uses auto commit. I've added an * by the nodes when interesting offsets appear.
Aapplication-level logs captured during the same time:
Going to update this consumer to v1.7.0, but thought I'd report this just in case. |
Description
Hi, before I get to the point I'd like to note that somewhat similar issue was reported already couple of times but each time the resolution was inconclusive.
In our setup we are using rust bindings to rdkafka and high level consumer with automatic commits and manual offset stores to achieve at least once delivery guarantee. Occasionally a situation occurs that our commited group offsets go back in time (i.e. reset to an offset commited a long time before). I'm still not entirely sure if i've found the root cause but I've found a way to reproduce that situation. I'd like to share the idea/code that reproduces this and ask for advice if this might be one of the following:
So, getting to the point, my guess was that automatic librdkafka commit takes place after a consumer got assigned a partition that was revoked from it before. This way, old, stored offsets are getting their way to the broker. I couldn't find a way to reproduce such situation with auto commits, so I went with manual commits taking place in the specific order between rebalance events. It goes like this:
topic[0]
).topic[0]
.1
). It stores this message usingrd_kafka_offset_store
. But does not commit it.topic[0]
, consumer A gets assigned to empty set of partitions at the same time.1
(this is normal - it was not committed). Offset1
is stored and committed synchronously usingrd_kafka_commit(.., NULL, ..)
2
), and commits it.rd_kafka_assign(.., NULL)
is called.rd_kafka_assign
is called withtopic_partition_list
prodivded by rebalance callback. Then, ard_kafka_commit(.., NULL, ..)
is called. The offset1
gets committed second time. If I'm not missing something, offset store should be reset duringrd_kafka_assign
, which providesRD_KAFKA_OFFSET_INVALID
offset for the partition.A workaround/fix that works with this case is to call
rd_kafka_offsets_store
when handling revoke, with previously assigned partitions and offsets set toRD_KAFKA_OFFSET_INVALID
(-1001
).Am I missing something or doing something obviously wrong here? And is it possible that such situation might occur with automatic commit?
How to reproduce
You could write code that executes steps described above or I can create minimal-ish example of rust code that helps expose such situation. Unfortunately I didn't use the latest librdkafka as it's not yet available in rust-rdkafka crate (https://github.com/fede1024/rust-rdkafka). You can find some logs (
debug=consumer,cgrp,topic
) in link below.Checklist
("bootstrap.servers", "localhost:9092"), ("group.id", "foo-test"), ("enable.auto.offset.store", "false", ("enable.auto.commit", "false"), ("auto.offset.reset", "earliest")
macos catalina 10.15.3
debug=..
as necessary) from librdkafka: https://gist.github.com/jacekchmiel/d80a01aa1b9b37aa70b32b333c3d5197The text was updated successfully, but these errors were encountered: