From 445abb979db324b23997ac14f12c51a04a714e8a Mon Sep 17 00:00:00 2001 From: Palash Chauhan Date: Wed, 12 Aug 2026 10:05:10 -0700 Subject: [PATCH] PHOENIX-7986 : Replace IndexCDCConsumer's exponential idle backoff with a fixed poll interval --- .../phoenix/hbase/index/IndexCDCConsumer.java | 26 ++++++++++++++----- .../end2end/IndexCDCConsumerLagIT.java | 1 - 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/IndexCDCConsumer.java b/phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/IndexCDCConsumer.java index 25b0e18f268..46423f0d87f 100644 --- a/phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/IndexCDCConsumer.java +++ b/phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/IndexCDCConsumer.java @@ -114,6 +114,13 @@ public class IndexCDCConsumer implements Runnable { "phoenix.index.cdc.consumer.poll.interval.ms"; private static final long DEFAULT_POLL_INTERVAL_MS = 500; + /** + * The interval in milliseconds between polls when the previous poll found no new events. + */ + public static final String INDEX_CDC_CONSUMER_IDLE_POLL_INTERVAL_MS = + "phoenix.index.cdc.consumer.idle.poll.interval.ms"; + private static final long DEFAULT_IDLE_POLL_INTERVAL_MS = 4000; + /** * The time buffer in milliseconds subtracted from current time when querying CDC mutations to * help avoid reading mutations that are too recent. @@ -157,6 +164,7 @@ public class IndexCDCConsumer implements Runnable { private final long startupDelayMs; private final int batchSize; private final long pollIntervalMs; + private final long idlePollIntervalMs; private final long timestampBufferMs; private final int maxDataVisibilityRetries; private final long parentProgressPauseMs; @@ -237,6 +245,10 @@ public IndexCDCConsumer(RegionCoprocessorEnvironment env, String dataTableName, this.batchSize = baseBatchSize + jitter; this.pollIntervalMs = config.getLong(INDEX_CDC_CONSUMER_POLL_INTERVAL_MS, DEFAULT_POLL_INTERVAL_MS); + long baseIdlePollInterval = + config.getLong(INDEX_CDC_CONSUMER_IDLE_POLL_INTERVAL_MS, DEFAULT_IDLE_POLL_INTERVAL_MS); + this.idlePollIntervalMs = + baseIdlePollInterval + ThreadLocalRandom.current().nextLong(baseIdlePollInterval / 5 + 1); this.timestampBufferMs = config.getLong(INDEX_CDC_CONSUMER_TIMESTAMP_BUFFER_MS, DEFAULT_TIMESTAMP_BUFFER_MS); this.maxDataVisibilityRetries = config.getInt(INDEX_CDC_CONSUMER_MAX_DATA_VISIBILITY_RETRIES, @@ -449,11 +461,11 @@ public void run() { lagEmissionEnabled = true; LOG.info( "IndexCDCConsumer started for table {} region {}" - + " [batchSize: {}, pollIntervalMs: {}, timestampBufferMs: {}, startupDelayMs: {}," - + " pause: {}, maxDataVisibilityRetries: {}, parentProgressPauseMs: {}," - + " serializeCDCMutations: {}]", - dataTableName, encodedRegionName, batchSize, pollIntervalMs, timestampBufferMs, - startupDelayMs, pause, maxDataVisibilityRetries, parentProgressPauseMs, + + " [batchSize: {}, pollIntervalMs: {}, idlePollIntervalMs: {}, timestampBufferMs: {}," + + " startupDelayMs: {}, pause: {}, maxDataVisibilityRetries: {}," + + " parentProgressPauseMs: {}, serializeCDCMutations: {}]", + dataTableName, encodedRegionName, batchSize, pollIntervalMs, idlePollIntervalMs, + timestampBufferMs, startupDelayMs, pause, maxDataVisibilityRetries, parentProgressPauseMs, serializeCDCMutations); if (!waitForCDCStreamEntry()) { LOG.error( @@ -502,10 +514,10 @@ public void run() { lastProcessedTimestamp = processCDCBatchGenerated(encodedRegionName, encodedRegionName, lastProcessedTimestamp, false); } + retryCount = 0; if (lastProcessedTimestamp == previousTimestamp) { - sleepWithLagSampling(ConnectionUtils.getPauseTime(pause, ++retryCount)); + sleepWithLagSampling(idlePollIntervalMs); } else { - retryCount = 0; sleepWithLagSampling(pollIntervalMs); } } catch (Exception e) { diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexCDCConsumerLagIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexCDCConsumerLagIT.java index 158c54d2767..db2ff8871e8 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexCDCConsumerLagIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexCDCConsumerLagIT.java @@ -58,7 +58,6 @@ public class IndexCDCConsumerLagIT extends ParallelStatsDisabledIT { private static final int TIMESTAMP_BUFFER_MS = 2_000; private static final int POLL_INTERVAL_MS = 500; private static final int LAG_SAMPLE_INTERVAL_MS = 500; - // Small retry pause so empty-poll backoff doesn't dominate idle behavior. private static final int RETRY_PAUSE_MS = 100; // Budget for the consumer to start up and emit its first lag sample. Generous because the // consumer waits up to INDEX_CDC_CONSUMER_STARTUP_DELAY_MS (default 10s) and then performs