Skip to content

HBASE-30433 Seed the master's flushedSequenceIdByRegion watermark with the region's final flushed seqid on region CLOSE - #8707

Merged
virajjasani merged 2 commits into
apache:masterfrom
nirdosh0110:HBASE-30433
Oct 17, 2026
Merged

virajjasani merged 2 commits into
apache:masterfrom
nirdosh0110:HBASE-30433

Conversation

@nirdosh0110

@nirdosh0110 nirdosh0110 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

JIRA: https://issues.apache.org/jira/browse/HBASE-30433

Summary

Seed the master's flushedSequenceIdByRegion watermark with the region's final flushed seqid on region CLOSE, so a subsequent WAL split of a drained/crashed source RS recognizes already-durable edits instead of writing orphaned recovered.edits.

Why

The master already seeds this watermark with openSeqNum at region OPEN. That is the correct primary fence and fires on every reopen path, but it leaves one narrow graceful-close window uncovered:

  1. A region is gracefully closed on the source RS (memstore flushed to the close marker).
  2. The source RS dies before the target RS finishes OPEN, so the OPEN-time seed has not fired.
  3. The source RS's SCP splits its WAL in that window, filtering against a still-stale flushedSequenceIdByRegion, and writes a (harmless-but-present) recovered.edits file.

Seeding on CLOSE advances the watermark to the region's reported flushed seqid before the source RS dies, closing this sub-window for the graceful-close case. This is additive: it does nothing for the pure-crash / never-gracefully-closed path (there is no close report), so the OPEN-time seed remains. Both writers go through the same monotonic merge(Math::max), so they compose safely and never regress a higher value.

Change

No protobuf/RPC change — the RegionStateTransition message already carries an optional openSeqNum field and the CLOSED transition is already routed through the same master-side handler.

  • RegionServer — CloseRegionHandler and UnassignRegionHandler report HRegion.getMaxFlushedSeqId() on the CLOSED transition (was HConstants.NO_SEQNUM). HRegionServer.createReportRegionStateTransitionRequest now sets the wire openSeqNum field for CLOSED too (when >= 0), not just OPENED.
  • Master — AssignmentManager seeds the watermark on the CLOSED transition via serverManager.advanceRegionFlushedSeq(regionInfo, seqId) when seqId >= 0 (the existing atomic max-merge).
  • Rename (review) — ServerManager#reportRegionOpen → advanceRegionFlushedSeq, since it now serves both OPEN and CLOSE; javadoc generalized. Callers and TestServerManager updated.

Test

Adds TestGetLastFlushedSequenceId#testFlushedSequenceIdSeededOnRegionClose: write rows without flushing, then disableTable (a graceful close that keeps the region — unlike delete/split/merge, disable does not call ServerManager#removeRegion). The close's own flush advances maxFlushedSeqId, and a heartbeat sent before the close cannot carry that value. The test asserts the master's watermark equals the post-close flushed seqid. Verified that it fails with the CLOSE seed disabled (expected: <7> but was: <2>). An earlier version flushed before the close and passed even without the fix, because the 1s heartbeats delivered the same value.

Local run on current master (JDK17): TestGetLastFlushedSequenceId 3/3, TestServerManager 5/5, TestMergeTableRegionsProcedure 9/9, TestAssignmentManagerUtil 3/3, TestMaster 7/7, TestDLSFSHLog 3/3, TestDLSAsyncFSWAL 3/3 green; spotless:check on hbase-server clean.

Note on stacking

Builds on #8584 (HBASE-30335, now merged to master), which introduced the OPEN-time seed (ServerManager.reportRegionOpen, renamed here to advanceRegionFlushedSeq) that this reuses. Rebased onto master: the first commit is the CLOSE-time seed, and the second addresses review feedback.

branch-2 backport: #8760.

…h the region's final flushed seqid on region CLOSE

On graceful region CLOSE the RegionServer now reports the region's durable
flushed seqid (HRegion.getMaxFlushedSeqId()) on the CLOSED transition, and the
master lifts its flushedSequenceIdByRegion watermark from it via the existing
monotonic reportRegionOpen(merge(Math::max)) seed. This narrows the graceful-close
window where a subsequent WAL split of a crashed source RS could otherwise treat
already-durable edits as unflushed and write orphaned recovered.edits.

No proto/RPC change: the RegionStateTransition message already carries an optional
openSeqNum field and the CLOSED transition is already routed through the same
master-side handler. HRegionServer now also sets that field for CLOSED (not just
OPENED), and AssignmentManager seeds the watermark on CLOSED when seqId >= 0.

Adds TestGetLastFlushedSequenceId#testFlushedSequenceIdSeededOnRegionClose.

@virajjasani virajjasani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left few comments, +1 otherwise

// write orphaned recovered.edits for already-durable edits. Uses the same monotonic
// merge(Math::max) seed, so it never regresses a higher value.
if (transition.getTransitionCode() == TransitionCode.CLOSED && seqId >= 0) {
master.getServerManager().reportRegionOpen(hri, seqId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since now region OPEN, FAILED_OPEN and CLOSED cases use the same ServerManager API, instead of calling it reportRegionOpen(), we can rename it to something generic like advanceRegionFlushedSeq().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since now region OPEN, FAILED_OPEN and CLOSED cases use the same ServerManager API, instead of calling it reportRegionOpen(), we can rename it to something generic like advanceRegionFlushedSeq().

Renamed the API to advanceRegionFlushedSeq(). JFYI FAILED_OPEN region state doesn't move the watermark forward, since a failed open has nothing new made durable to report.

Comment on lines +195 to +197
assertTrue(ids.getLastFlushedSequenceId() >= flushedSeqId,
"CLOSE seed " + ids.getLastFlushedSequenceId() + " must be >= the region's flushed seqid "
+ flushedSeqId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After retrieving flushedSeqId, since we are only disabling the table, is it possible for ids.getLastFlushedSequenceId() to be greater than flushedSeqId? Or they both should be same?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they should be equal. A close only flushes when there's data in the memstore, and the heartbeat reports the same maxFlushedSeqId, so nothing can push the value above it. I've changed the unit test also to leave edits unflushed, so the close's own flush moves the seqid forward. It now uses assertEquals, and it fails without the fix

…n close-seed test

- Rename ServerManager#reportRegionOpen to advanceRegionFlushedSeq since it is
  now called on both region OPEN and CLOSE; generalize its javadoc.
- testFlushedSequenceIdSeededOnRegionClose now leaves edits unflushed so the
  close flush itself advances maxFlushedSeqId (a pre-close heartbeat cannot
  carry that value), and asserts the master's watermark equals it. The old
  version passed even with the CLOSE seed disabled because 1s heartbeats
  delivered the same value.
@virajjasani

Copy link
Copy Markdown
Contributor

Awaiting workflow results

@virajjasani
virajjasani merged commit 6448aa6 into apache:master Oct 17, 2026
8 checks passed
virajjasani pushed a commit that referenced this pull request Oct 17, 2026
…h the region's final flushed seqid on region CLOSE (#8707)

Signed-off-by: Viraj Jasani <vjasani@apache.org>
virajjasani pushed a commit that referenced this pull request Oct 17, 2026
…h the region's final flushed seqid on region CLOSE (#8707)

Signed-off-by: Viraj Jasani <vjasani@apache.org>
virajjasani pushed a commit that referenced this pull request Oct 17, 2026
…h the region's final flushed seqid on region CLOSE (#8760) (#8707)

Signed-off-by: Viraj Jasani <vjasani@apache.org>
virajjasani pushed a commit that referenced this pull request Oct 17, 2026
…h the region's final flushed seqid on region CLOSE (#8760) (#8707)

Signed-off-by: Viraj Jasani <vjasani@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants