Skip to content

Commit 94ede7f

Browse files
committed
feat(core): reuse unregistered node when requesting for next node id (#2183)
Signed-off-by: Shichao Nie <[email protected]>
1 parent d6641d7 commit 94ede7f

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

metadata/src/main/java/org/apache/kafka/controller/ClusterControlManager.java

+30-5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.apache.kafka.server.common.MetadataVersion;
5757
import org.apache.kafka.timeline.SnapshotRegistry;
5858
import org.apache.kafka.timeline.TimelineHashMap;
59+
import org.apache.kafka.timeline.TimelineHashSet;
5960

6061
import org.slf4j.Logger;
6162

@@ -292,6 +293,11 @@ boolean check() {
292293
* The real next available node id is generally one greater than this value.
293294
*/
294295
private AtomicInteger nextNodeId = new AtomicInteger(-1);
296+
297+
/**
298+
* A set of node IDs that have been unregistered and can be reused for new node assignments.
299+
*/
300+
private final TimelineHashSet<Integer> reusableNodeIds;
295301
// AutoMQ for Kafka inject end
296302

297303
private ClusterControlManager(
@@ -323,6 +329,7 @@ private ClusterControlManager(
323329
this.brokerUncleanShutdownHandler = brokerUncleanShutdownHandler;
324330
// AutoMQ for Kafka inject start
325331
this.maxControllerId = QuorumConfig.parseVoterConnections(quorumVoters).keySet().stream().max(Integer::compareTo).orElse(0);
332+
this.reusableNodeIds = new TimelineHashSet<>(snapshotRegistry, 0);
326333
// AutoMQ for Kafka inject end
327334
}
328335

@@ -369,11 +376,21 @@ boolean zkRegistrationAllowed() {
369376

370377
// AutoMQ for Kafka inject start
371378
public ControllerResult<Integer> getNextNodeId() {
372-
int maxBrokerId = brokerRegistrations.keySet().stream().max(Integer::compareTo).orElse(0);
373-
int maxNodeId = Math.max(maxBrokerId, maxControllerId);
374-
int nextId = this.nextNodeId.accumulateAndGet(maxNodeId, (x, y) -> Math.max(x, y) + 1);
375-
// Let the broker's nodeId start from 1000 to easily distinguish broker and controller.
376-
nextId = Math.max(nextId, 1000);
379+
int nextId;
380+
if (!reusableNodeIds.isEmpty()) {
381+
Iterator<Integer> iterator = reusableNodeIds.iterator();
382+
nextId = iterator.next();
383+
// we simply remove the id from reusable id set because we're unable to determine if the id
384+
// will finally be used.
385+
iterator.remove();
386+
} else {
387+
int maxBrokerId = brokerRegistrations.keySet().stream().max(Integer::compareTo).orElse(0);
388+
int maxNodeId = Math.max(maxBrokerId, maxControllerId);
389+
nextId = this.nextNodeId.accumulateAndGet(maxNodeId, (x, y) -> Math.max(x, y) + 1);
390+
// Let the broker's nodeId start from 1000 to easily distinguish broker and controller.
391+
nextId = Math.max(nextId, 1000);
392+
}
393+
377394
UpdateNextNodeIdRecord record = new UpdateNextNodeIdRecord().setNodeId(nextId);
378395

379396
List<ApiMessageAndVersion> records = new ArrayList<>();
@@ -583,6 +600,11 @@ public void replay(RegisterBrokerRecord record, long offset) {
583600
if (prevRegistration != null) heartbeatManager.remove(brokerId);
584601
heartbeatManager.register(brokerId, record.fenced());
585602
}
603+
604+
// AutoMQ injection start
605+
reusableNodeIds.remove(brokerId);
606+
// AutoMQ injection end
607+
586608
if (prevRegistration == null) {
587609
log.info("Replayed initial RegisterBrokerRecord for broker {}: {}", record.brokerId(), record);
588610
} else if (prevRegistration.incarnationId().equals(record.incarnationId())) {
@@ -608,6 +630,9 @@ public void replay(UnregisterBrokerRecord record) {
608630
if (heartbeatManager != null) heartbeatManager.remove(brokerId);
609631
updateDirectories(brokerId, registration.directories(), null);
610632
brokerRegistrations.remove(brokerId);
633+
// AutoMQ injection start
634+
reusableNodeIds.add(brokerId);
635+
// AutoMQ injection end
611636
log.info("Replayed {}", record);
612637
}
613638
}

0 commit comments

Comments
 (0)