Skip to content
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

Fix sequence change race condition #14805

Closed
wants to merge 20 commits into from
Closed

Fix sequence change race condition #14805

wants to merge 20 commits into from

Conversation

panhongan
Copy link
Contributor

@panhongan panhongan commented Aug 13, 2023

Fixes #XXXX.
org.apache.druid.indexing.seekablestream.SeekableStreamIndexTaskRunner#maybePersistAndPublishSequences

Description

Exception: org.apache.druid.java.util.common.ISE: Attempting to publish with empty segment set, but total row count was not 0: [257963].

Context:
intermediateHandoffPeriod: PT20M

Case Analysis:

18:20 ingestion task started with sequence:

[
SequenceMetadata
{sequenceId=0, sequenceName='datasource.1_ec6e2d1b6806983_0', 
assignments=[162, 2, 82, 202, 42, 122], 
startOffsets={162=652113981, 82=652884857, 2=1235731042, 202=655877162, 122=660321166, 42=1231522559}, 
exclusiveStartPartitions=[], 
endOffsets={162=9223372036854775807, 2=9223372036854775807, 82=9223372036854775807, 202=9223372036854775807, 42=9223372036854775807, 122=9223372036854775807}, 
sentinel=false, 
checkpointed=true
}
]

===================================
18:40 1st hand-off succeed with sequence:

[
SequenceMetadata
{sequenceId=0, sequenceName='datasource.1_ec6e2d1b6806983_0', 
assignments=[162, 2, 82, 202, 42, 122], 
startOffsets={162=652113981, 82=652884857, 2=1235731042, 202=655877162, 122=660321166, 42=1231522559}, 
exclusiveStartPartitions=[], 
endOffsets={162=652421674, 2=1236043200, 82=653189675, 202=656183403, 42=1231829967, 122=660629209}, 
sentinel=false, 
checkpointed=true
}
]

2023-08-06T18:40:26,525 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.BaseAppenderatorDriver - Pushing [2] segments in background
2023-08-06T18:40:26,526 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.BaseAppenderatorDriver - Pushing segments: [
datasource.1_2023-08-06T18:15:00.000Z_2023-08-06T18:30:00.000Z_2023-08-06T17:27:23.279Z_91,
datasource.1_2023-08-06T18:30:00.000Z_2023-08-06T18:45:00.000Z_2023-08-06T17:17:58.416Z_12
]

===========================
19:00 2nd hand-off succeed with sequence:

[
SequenceMetadata
{sequenceId=1, sequenceName='datasource.1_ec6e2d1b6806983_1', 
assignments=[162, 2, 82, 202, 42, 122], 
startOffsets={162=652421674, 2=1236043200, 82=653189675, 202=656183403, 42=1231829967, 122=660629209}, 
exclusiveStartPartitions=[], 
endOffsets={162=652734796, 2=1236359960, 82=653501954, 202=656497034, 42=1232144385, 122=660942851}, 
sentinel=false, 
checkpointed=true
}
] 

2023-08-06T19:00:26,069 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.BaseAppenderatorDriver - Pushing [3] segments in background
2023-08-06T19:00:26,070 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.BaseAppenderatorDriver - Pushing segments: [
datasource.1_2023-08-06T18:30:00.000Z_2023-08-06T18:45:00.000Z_2023-08-06T17:17:58.416Z_54,
datasource.1_2023-08-06T18:45:00.000Z_2023-08-06T19:00:00.000Z_2023-08-06T17:25:18.834Z_38,
datasource.1_2023-08-06T19:00:00.000Z_2023-08-06T19:15:00.000Z_2023-08-06T18:20:49.142Z_39
]

==============================
Go on running with 3rd sequence:

[
SequenceMetadata{
sequenceId=2, sequenceName='datasource.1_ec6e2d1b6806983_2', 
assignments=[162, 2, 82, 202, 42, 122], 
startOffsets={162=652734796, 2=1236359960, 82=653501954, 202=656497034, 42=1232144385, 122=660942851}, 
exclusiveStartPartitions=[], 
endOffsets={162=9223372036854775807, 2=9223372036854775807, 82=9223372036854775807, 202=9223372036854775807, 42=9223372036854775807, 122=9223372036854775807}, 
sentinel=false, 
checkpointed=false
}
]

2023-08-06T19:02:58,507 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.BaseAppenderatorDriver - Pushing [0] segments in background
2023-08-06T19:02:58,507 INFO [task-runner-0-priority-0] org.apache.druid.segment.realtime.appenderator.StreamAppenderator - Persisted rows[0] and (estimated) bytes[0]
2023-08-06T19:02:58,509 Error while publishing segments for sequenceNumber
[
SequenceMetadata{
sequenceId=1, sequenceName='datasource.1_ec6e2d1b6806983_1',
assignments=[],
startOffsets={162=652421674, 2=1236043200, 82=653189675, 202=656183403, 42=1231829967, 122=660629209},
exclusiveStartPartitions=[],
endOffsets={162=652734796, 2=1236359960, 82=653501954, 202=656497034, 42=1232144385, 122=660942851},
sentinel=false, checkpointed=true
}
]

org.apache.druid.java.util.common.ISE: Attempting to publish with empty segment set, but total row count was not 0: [257963].

Question:

  1. At 19:00, sequenceName='datasource.1_ec6e2d1b6806983_1' already finished with hand-off segment succeed. But why there was another segment pushing with number 0 ?
  2. In the failed sequence metadata, why assignments is empty?

Related Source Code:
By checking the source code, found that there is an race condition issue:

Code Block A:maybePersistAndPublishSequences()

for (SequenceMetadata<PartitionIdType, SequenceOffsetType> sequenceMetadata : sequences) {
  sequenceMetadata.updateAssignments(currOffsets, this::isMoreToReadBeforeReadingRecord);
  if (!sequenceMetadata.isOpen() && !publishingSequences.contains(sequenceMetadata.getSequenceName())) {
    publishingSequences.add(sequenceMetadata.getSequenceName());
    try {
      final Object result = driver.persist(committerSupplier.get());
      log.debug(
                "Persist completed with metadata [%s], adding sequence [%s] to publish queue.",
                result,
                sequenceMetadata.getSequenceName()
      );
      publishAndRegisterHandoff(sequenceMetadata);
    }
    catch (InterruptedException e) {
      log.warn("Interrupted while persisting metadata for sequence [%s].", sequenceMetadata.getSequenceName());
      throw e;
    }
  }
}

Code Block B:After pushing segment metadata succeed

sequences.remove(sequenceMetadata);
publishingSequences.remove(sequenceMetadata.getSequenceName());

Fixed the bug ...

Renamed the class ...

Added a forbidden-apis entry ...

Release note


Key changed/added classes in this PR
  • org.apache.druid.indexing.seekablestream.SeekableStreamIndexTaskRunner#maybePersistAndPublishSequences

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

@pranavbhole
Copy link
Contributor

@panhongan Thank you for PR, can you please elaborate the issue ?

@panhongan panhongan marked this pull request as draft September 15, 2023 02:51
@panhongan panhongan marked this pull request as ready for review September 15, 2023 07:39
@abhishekagarwal87
Copy link
Contributor

Is it same as #14995? cc @AmatyaAvadhanula

@panhongan
Copy link
Contributor Author

panhongan commented Oct 5, 2023

Is it same as #14995? cc @AmatyaAvadhanula

Yes, that's the same issue. But there was race condition, need to safely handle that.
I tested my change in my personal druid cluster, and also for unit test.

@panhongan
Copy link
Contributor Author

panhongan commented Oct 7, 2023

@pranavbhole @abhishekagarwal87 @kfaraz Can you help review and merge?

@AmatyaAvadhanula
Copy link
Contributor

Hi @panhongan. It seems like the new tests pass with or without the changes. Could you please try adding more deterministic tests if possible?

@panhongan
Copy link
Contributor Author

Hi @panhongan. It seems like the new tests pass with or without the changes. Could you please try adding more deterministic tests if possible?

@AmatyaAvadhanula @abhishekagarwal87 I improved the unit test. Also I see the #14995 was merged to fix the same issue. From my side, synchronized may be more straightforward to fix race condition issue.
Not sure is there any chance to merge my PR? Thanks.

@kfaraz
Copy link
Contributor

kfaraz commented Dec 16, 2023

@panhongan , do you still see the issue happening after #14995 was merged?
You could try updating this PR to just contain the tests that verify the fix that was done in #14995.

Copy link

This pull request has been marked as stale due to 60 days of inactivity.
It will be closed in 4 weeks if no further activity occurs. If you think
that's incorrect or this pull request should instead be reviewed, please simply
write any comment. Even if closed, you can still revive the PR at any time or
discuss it on the [email protected] list.
Thank you for your contributions.

@github-actions github-actions bot added the stale label Feb 19, 2024
@panhongan panhongan closed this Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants