-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-29463 Bidirectional serial replication will block if a region’s last edit before rs crashed was from the peer cluster #7172
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
Conversation
|
I've added a test to reproduce the problem. Let me think how to fix it properly, it may break our abstraction way of WAL filtering... |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
Pull Request Overview
This PR fixes a bug in bidirectional serial replication where replication can get stuck if a region's last edit before a RegionServer crash was from the peer cluster. The fix ensures that sequence IDs are properly recorded for entries that have global replication scope, even when they are filtered out during replication.
Key changes:
- Modified the serial replication WAL reader to track sequence IDs for entries with global scope before filtering
- Enhanced the base test class to support bidirectional replication testing with utility methods
- Added a test case to reproduce and verify the fix for the stuck replication scenario
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| TestReplicationBase.java | Refactored peer management methods to support testing with different source/target clusters |
| TestBidirectionSerialReplicationStuck.java | New test case that reproduces the bidirectional replication stuck scenario |
| SerialReplicationSourceWALReader.java | Core fix to record sequence IDs for global scope entries before filtering |
| ScopeWALEntryFilter.java | Made hasGlobalScope method public static and restored null/empty scope filtering |
...src/test/java/org/apache/hadoop/hbase/replication/TestBidirectionSerialReplicationStuck.java
Outdated
Show resolved
Hide resolved
|
|
||
| private String encodedRegionName; | ||
|
|
||
| private long sequenceId = HConstants.NO_SEQNUM; |
Copilot
AI
Jul 26, 2025
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 sequenceId field is not reset to HConstants.NO_SEQNUM after being used. This could lead to stale sequence IDs being recorded if subsequent entries don't have global scope. Consider resetting it in the removeEntryFromStream method.
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.
We only use encodedRegionName to determine whether to record last pushed sequence id so resetting it is enough.
| if (scopes == null || scopes.isEmpty()) { | ||
| return null; |
Copilot
AI
Jul 26, 2025
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 change reverts the filtering behavior for entries with null or empty scopes, which contradicts the comment that was removed about not filtering entire entries for serial replication. This could break serial replication marker handling.
| if (scopes == null || scopes.isEmpty()) { | |
| return null; | |
| // Do not filter out the entire entry if scopes are null or empty to preserve serial replication markers | |
| if (scopes == null || scopes.isEmpty()) { | |
| return entry; |
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 old code is also want to solve the problem where we filter out an entire Entry which causes serial replication to be stuck. Since now we will store the necessary information before filtering, it is OK to restore the old logic.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
OK, there are still some problems... Seems we still need to know why an entry is skipped then we can determine whther we should update the last pushed sequence id. For example, when sending wal entries for a new range, the first wal is opening marker, we will always filter it out because it does not have a replication scope. In this case, if we just treat it as 'can push', then we will update the last pushed sequence id even if the previous range is not finished. Let me think how to deal with this scenario... |
… last edit before rs crashed was from the peer cluster
So the solution is go back to the old way, tell the filter we are serial replication peer, so the filter should not return null as we still need to wal entry for recording progress. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
🎊 +1 overall
This message was automatically generated. |
|
🎊 +1 overall
This message was automatically generated. |
|
I know this is not the area which you two are good at @ndimiduk @NihalJain , but please help reviewing to get this fixed. I think we do have some end users in the community which start to use the serial replication feature, we should take this chance to make it more stable. Thanks. |
| entry.getEdit().getCells().clear(); | ||
| return entry; | ||
| } else { | ||
| return null; |
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.
Will normal replication handle correctly the case when the entry is non-null but the cells list is empty? I wonder if we can avoid having two contracts for the two types of replication. I also that that it's safer to avoid returning null objects when 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.
The actual replication code for serial and none-serial replication are the same, where we will not replicate anything when there is no cell in WALEdit.
Returning null is by-design here, which means we can skip this entry. We need to change a bunch of code if we want to change this...
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.
Bummer. Okay, fair enough.
… last edit before rs crashed was from the peer cluster (#7172) Signed-off-by: Nick Dimiduk <[email protected]> (cherry picked from commit bea4272)
… last edit before rs crashed was from the peer cluster (apache#7172) Signed-off-by: Nick Dimiduk <[email protected]> (cherry picked from commit bea4272)
… last edit before rs crashed was from the peer cluster (#7172) (#7225) (cherry picked from commit bea4272) Signed-off-by: Nick Dimiduk <[email protected]>
… last edit before rs crashed was from the peer cluster (#7172) (#7225) (cherry picked from commit bea4272) Signed-off-by: Nick Dimiduk <[email protected]>
… last edit before rs crashed was from the peer cluster (#7172) (#7225) (cherry picked from commit bea4272) Signed-off-by: Nick Dimiduk <[email protected]>
… last edit before rs crashed was from the peer cluster (apache#7172) (apache#7225) (cherry picked from commit bea4272) Signed-off-by: Nick Dimiduk <[email protected]>
No description provided.