-
Notifications
You must be signed in to change notification settings - Fork 14k
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
KAFKA-13249: Always update changelog offsets before writing the checkpoint file #11283
Conversation
516f9e5
to
cbb8c99
Compare
Hey @hutchiko , thanks for digging into this bug so thoroughly and providing a patch! One quick question before I review -- does this only affect version 2.8 or below specifically, or could this be present on trunk/3.0 as well? Unless you already checked this, my guess would be the latter. If you can verify that is true, then can you please retarget this PR against the |
@@ -565,7 +565,7 @@ public void closeCleanAndRecycleState() { | |||
protected void maybeWriteCheckpoint(final boolean enforceCheckpoint) { | |||
// commitNeeded indicates we may have processed some records since last commit | |||
// and hence we need to refresh checkpointable offsets regardless whether we should checkpoint or not | |||
if (commitNeeded) { | |||
if (commitNeeded || enforceCheckpoint) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we just removed the check altogether? It's not like updating the changelog offsets is a particularly "heavy" call, we may as well future-proof things even more by just updating the offsets any time.
In fact, why do we even have this weird split brain logic to begin with...it would make more sense to just update the offsets inside the StreamTask#maybeWriteCheckpoint
and stateMgr.checkpoint()
methods, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the same thing but not knowing enough about all the streams internals I thought I'd just go with the most minimal change possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason that I added this check is that checkpointableOffsets()
can potentially be expensive. I think the fix to have commitNeeded || enforceCheckpoint
is actually elegant as we did not introduce extra unnecessary overhead much, since it is only true when closing the task.
@ableegoldman I did not test against 3.0 just 2.7 and 2.8. I'll rebase onto |
…with change log after clean shutdown Adds test to verify that state store and checkpoint file are in sync with change log after clean shutdown
Yeah I've rebased and verified the issue is there in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM, but there was a relevant failure in the build: https://ci-builds.apache.org/job/Kafka/job/kafka-pr/job/PR-11283/5/testReport/org.apache.kafka.streams.integration/EosIntegrationTest/Build___JDK_16_and_Scala_2_13___shouldWriteLatestOffsetsToCheckpointOnShutdown_at_least_once_/
Guessing it's just some flakiness in the test, can you check that out before I merge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch! Thanks for the quick fix @hutchiko !
@@ -565,7 +565,7 @@ public void closeCleanAndRecycleState() { | |||
protected void maybeWriteCheckpoint(final boolean enforceCheckpoint) { | |||
// commitNeeded indicates we may have processed some records since last commit | |||
// and hence we need to refresh checkpointable offsets regardless whether we should checkpoint or not | |||
if (commitNeeded) { | |||
if (commitNeeded || enforceCheckpoint) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason that I added this check is that checkpointableOffsets()
can potentially be expensive. I think the fix to have commitNeeded || enforceCheckpoint
is actually elegant as we did not introduce extra unnecessary overhead much, since it is only true when closing the task.
@hutchiko I looked at the test code, and it seems to me there's indeed a timing-related flakiness. Could you try to fix it before we merge (you can first try to reproduce it, e.g. on IDE with repeated runs and see how often it could fail; and after you fix it usually we would try to verify that after say 1000 runs, there's no more failure). |
4a3df41
to
39f2634
Compare
…ct to timing related flakiness.
39f2634
to
bfeb484
Compare
@guozhangwang @ableegoldman unfortunately I could never reproduce the CI failures however I have pushed up a refactor of the method which I think was responsible for the flakiness. The original version of the the method was scanning backwards through the changelog topic searching for the top record so I could cross check that record's offset with the checkpointed offset. It had an implicit assumption that the consumer it was driving backwards would always get some records after a 50ms I switched the logic around so it just consumes forwards until it finds the end of the topic there are no assumptions about timing in the new logic so I'm hoping that will fix the flakiness. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @hutchiko for the updated tests. I agree that with 10 recs written to partition, reading forward is easier, and not polling for 50ms only makes sense (since with EOS some offsets would just be txn markers).
I checked the failures of the new run and they are not related to the new tests. Merging to trunk now. |
…point file (#11283) When using EOS checkpointed offsets are not updated to the latest offsets from the changelog because the maybeWriteCheckpoint method is only ever called when commitNeeded=false. This change will force the update if enforceCheckpoint=true . I have also added a test which verifies that both the state store and the checkpoint file are completely up to date with the changelog after the app has shutdown. Reviewers: Anna Sophie Blee-Goldman <ableegoldman@apache.org>, Guozhang Wang <wangguoz@gmail.com>
cc @kkonstantine , this is a critical bug fix hence I'm cherry-picking to 3.0 as well. If RC2 is voted through then it will fall on 3.0.1, otherwise if we vote for another RC3 I think it'd be a great-to-have in 3.0.0 |
@guozhangwang can you cherrypick this back to 2.8 at least? Maybe also 2.7 if there aren't any conflicts (seems like it should be a smooth merge but 🤷♀️ ) |
…point file (#11283) When using EOS checkpointed offsets are not updated to the latest offsets from the changelog because the maybeWriteCheckpoint method is only ever called when commitNeeded=false. This change will force the update if enforceCheckpoint=true . I have also added a test which verifies that both the state store and the checkpoint file are completely up to date with the changelog after the app has shutdown. Reviewers: Anna Sophie Blee-Goldman <ableegoldman@apache.org>, Guozhang Wang <wangguoz@gmail.com>
I resolved some conflicts and cherry-picked to 2.8; there are too many conflicts in 2.7 though. |
@guozhangwang Now that |
SG, will cherry-pick. |
…point file (apache#11283) When using EOS checkpointed offsets are not updated to the latest offsets from the changelog because the maybeWriteCheckpoint method is only ever called when commitNeeded=false. This change will force the update if enforceCheckpoint=true . I have also added a test which verifies that both the state store and the checkpoint file are completely up to date with the changelog after the app has shutdown. Reviewers: Anna Sophie Blee-Goldman <ableegoldman@apache.org>, Guozhang Wang <wangguoz@gmail.com>
…point file (apache#11283) When using EOS checkpointed offsets are not updated to the latest offsets from the changelog because the maybeWriteCheckpoint method is only ever called when commitNeeded=false. This change will force the update if enforceCheckpoint=true . I have also added a test which verifies that both the state store and the checkpoint file are completely up to date with the changelog after the app has shutdown. Reviewers: Anna Sophie Blee-Goldman <ableegoldman@apache.org>, Guozhang Wang <wangguoz@gmail.com>
When using EOS checkpointed offsets are not updated to the latest offsets from the changelog because the
maybeWriteCheckpoint
method is only ever called whencommitNeeded=false
. This change will force the update ifenforceCheckpoint=true
.I have also added a test which verifies that both the state store and the checkpoint file are completely up to date with the changelog after the app has shutdown.