KafkaIQ

2.2 Broker-Side Partition & Leader Management

Module Overview

Goal: Understand how Kafka brokers manage partition leadership and distribution — a complementary perspective to consumer-side coordination.

What You'll Learn:

  • How partition leaders are distributed across brokers
  • Automatic leader rebalancing mechanisms
  • Leader vs follower replica roles
  • Manual partition reassignment tools
  • Rack awareness for high availability
  • Tuning considerations for large clusters

What's NOT Covered Here:

  • Consumer group partition assignment (covered in Module 3.1)
  • Consumer rebalancing (covered in Module 4.1)
  • Producer partitioning strategy (covered in Producer modules)

Key Insight: While consumers assign partitions among themselves, brokers manage which broker leads each partition. This is orthogonal to consumer coordination but affects availability and performance.


1. Partition Leadership Basics

Leaders vs Followers

Every partition has multiple replicas for fault tolerance:

Topic: "orders", Partition 0, Replication Factor: 3

┌────────────────────────────────────────────┐
│ Broker 1: LEADER (Partition 0)            │
│  ├─ Handles all reads and writes          │
│  ├─ Coordinates follower replication      │
│  └─ Responds to producer/consumer requests │
└────────────────────────────────────────────┘
         │
         ├──── replication ────→ ┌────────────────────────┐
         │                        │ Broker 2: FOLLOWER     │
         │                        │  └─ Receives updates   │
         │                        └────────────────────────┘
         │
         └──── replication ────→ ┌────────────────────────┐
                                  │ Broker 3: FOLLOWER     │
                                  │  └─ Receives updates   │
                                  └────────────────────────┘

Key Roles:

Role Responsibilities
Leader • Handles all produce requests<br>• Handles all consume requests<br>• Manages ISR (In-Sync Replicas)<br>• Coordinates replication
Follower • Fetches data from leader<br>• Maintains replica<br>• Can become leader if current leader fails<br>• No direct client interaction

Why This Matters:

  • Only the leader serves client requests
  • If leaders are unevenly distributed, some brokers become bottlenecks
  • Automatic leader rebalancing prevents hotspots

Preferred Leader

Each partition has a preferred leader — the replica that Kafka prefers to be the leader.

Topic: "orders", Partition 0
Replicas: [1, 2, 3]  ← Broker 1 is the preferred leader
         ↑
         Preferred Leader (first in list)

Topic: "orders", Partition 1
Replicas: [2, 3, 1]  ← Broker 2 is the preferred leader
         ↑
         Preferred Leader

Preferred Leader Election:

  • By default, the first replica in the replica list is the preferred leader
  • Kafka tries to keep the preferred leader as the actual leader
  • This distributes leadership evenly across brokers

2. Leader Rebalancing Configurations

The Problem: Leader Skew

Scenario: 3-broker cluster, 12 partitions

Initial (balanced):
Broker 1: Leader for P0, P3, P6, P9      (4 leaders)
Broker 2: Leader for P1, P4, P7, P10     (4 leaders)
Broker 3: Leader for P2, P5, P8, P11     (4 leaders)

After Broker 2 crashes and recovers:
Broker 1: Leader for P0, P1, P3, P4, P6, P7, P9, P10  (8 leaders!)
Broker 2: Leader for NONE                              (0 leaders)
Broker 3: Leader for P2, P5, P8, P11                   (4 leaders)

Result: Broker 1 is overloaded, Broker 2 is idle

Solution: Automatic leader rebalancing moves leadership back to preferred leaders.


Configuration: auto.leader.rebalance.enable

# Enable automatic leader rebalancing (default: true)
auto.leader.rebalance.enable=true

What It Does:

  • Kafka periodically checks for leader imbalance
  • If imbalance exceeds threshold, triggers preferred leader election
  • Moves leadership back to preferred replicas

When to Disable:

  • During maintenance windows
  • If you prefer manual control
  • In very large clusters with frequent changes

Configuration: leader.imbalance.check.interval.ms

# How often to check for leader imbalance (default: 5 minutes)
leader.imbalance.check.interval.ms=300000

What It Does:

  • Controls frequency of leader balance checks
  • Lower values = faster rebalancing but more overhead
  • Higher values = slower rebalancing but less overhead

Tuning Guidance:

Cluster Size Recommended Interval Reason
Small (< 10 brokers) 300000 (5 min) Default works well
Medium (10-50 brokers) 300000-600000 Reduce overhead
Large (> 50 brokers) 600000-900000 Minimize controller load

Configuration: leader.imbalance.per.broker.percentage

# Trigger rebalancing if imbalance exceeds 10% (default)
leader.imbalance.per.broker.percentage=10

How It's Calculated:

Leader Imbalance % = (Actual Leaders - Expected Leaders) / Expected Leaders × 100

Example:
Expected Leaders per Broker: 100
Broker 1 Actual Leaders: 115

Imbalance = (115 - 100) / 100 × 100 = 15%

Since 15% > 10% (threshold), rebalancing triggers

Tuning Guidance:

Threshold Behavior Use Case
5% Very aggressive rebalancing Small clusters, need perfect balance
10% (default) Balanced approach Most production use cases
20% Relaxed rebalancing Large clusters, prefer stability over balance

Configuration: unclean.leader.election.enable

# Allow out-of-sync replicas to become leader (default: false)
unclean.leader.election.enable=false

What It Controls:

Scenario: Leader dies, all ISR replicas also unavailable

Option 1: unclean.leader.election.enable=false
├─ Wait for ISR replica to come back
├─ Partition remains unavailable
└─ NO DATA LOSS

Option 2: unclean.leader.election.enable=true
├─ Elect out-of-sync replica as leader
├─ Partition becomes available immediately
└─ POTENTIAL DATA LOSS (replica may be behind)

Availability vs Durability Trade-off:

Setting Availability Durability Use Case
false (default) Lower (partition unavailable if no ISR) Higher (no data loss) Financial systems, critical data
true Higher (always elect a leader) Lower (potential data loss) Metrics, logs, non-critical data

⚠️ Warning: Enabling unclean leader election can cause:

  • Message loss
  • Offset inconsistencies
  • Consumer confusion (messages may "disappear")

3. Manual Partition Reassignment

When to Use Manual Reassignment

Common Scenarios:
1. Adding new brokers to cluster
   → Redistribute partitions to new brokers

2. Decommissioning brokers
   → Move partitions off broker before shutdown

3. Fixing imbalanced partition distribution
   → Manually rebalance storage or network load

4. Rack awareness configuration
   → Ensure replicas spread across racks/AZs

Tool: kafka-reassign-partitions.sh

Step 1: Generate Reassignment Plan

# Create topics.json with topics to reassign
cat > topics.json <<EOF
{
  "topics": [
    {"topic": "orders"},
    {"topic": "payments"}
  ],
  "version": 1
}
EOF

# Generate reassignment plan for specific brokers
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --topics-to-move-json-file topics.json \
  --broker-list "0,1,2,3" \
  --generate

# Output:
# Current partition assignment:
# {"version":1,"partitions":[{"topic":"orders","partition":0,"replicas":[0,1]},...]}
#
# Proposed partition reassignment:
# {"version":1,"partitions":[{"topic":"orders","partition":0,"replicas":[2,3]},...]}

Step 2: Execute Reassignment

# Save proposed reassignment to file
cat > reassignment.json <<EOF
{
  "version": 1,
  "partitions": [
    {"topic": "orders", "partition": 0, "replicas": [2, 3]},
    {"topic": "orders", "partition": 1, "replicas": [3, 0]},
    ...
  ]
}
EOF

# Execute reassignment
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --execute

# Monitor progress
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --verify

Using Kafka Admin API for Reassignment

import org.apache.kafka.clients.admin.*;
import org.apache.kafka.common.TopicPartitionReplica;

Properties props = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");

try (AdminClient admin = AdminClient.create(props)) {
    // Define new replica assignment
    Map<TopicPartition, Optional<NewPartitionReassignment>> reassignments = Map.of(
        new TopicPartition("orders", 0),
        Optional.of(new NewPartitionReassignment(Arrays.asList(2, 3, 0))),
        
        new TopicPartition("orders", 1),
        Optional.of(new NewPartitionReassignment(Arrays.asList(3, 0, 1)))
    );

    // Execute reassignment
    AlterPartitionReassignmentsResult result = 
        admin.alterPartitionReassignments(reassignments);
    
    result.all().get(); // Wait for completion
    
    System.out.println("Partition reassignment initiated");
    
    // List ongoing reassignments
    ListPartitionReassignmentsResult listResult = 
        admin.listPartitionReassignments();
    
    Map<TopicPartition, PartitionReassignment> ongoing = 
        listResult.reassignments().get();
    
    ongoing.forEach((tp, reassignment) -> {
        System.out.printf("Partition %s: %s -> %s%n",
            tp,
            reassignment.replicas(),
            reassignment.addingReplicas());
    });
}

Throttling Reassignment Traffic

Problem: Partition reassignment can saturate network bandwidth, affecting production traffic.

Solution: Throttle replication bandwidth:

# Set replication throttle to 50 MB/s per broker
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --execute \
  --throttle 50000000

# Remove throttle after reassignment completes
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --verify

# Manually remove throttle if needed
kafka-configs.sh \
  --bootstrap-server localhost:9092 \
  --entity-type brokers \
  --entity-name 0 \
  --alter \
  --delete-config leader.replication.throttled.rate,follower.replication.throttled.rate

Throttle Configuration:

Throttle Rate Impact Use Case
No throttle Fast reassignment, may impact production Off-peak, low-traffic periods
50-100 MB/s Moderate reassignment, minimal impact Most production scenarios
10-20 MB/s Slow reassignment, no production impact High-traffic, latency-sensitive workloads

4. Rack Awareness

What is Rack Awareness?

Rack Awareness ensures replicas are distributed across different physical racks or availability zones (AZs) for fault tolerance.

Without Rack Awareness:
Rack A: Broker 1 (Leader), Broker 2 (Follower), Broker 3 (Follower)
Rack B: Broker 4, Broker 5, Broker 6

If Rack A fails → All replicas lost → Data unavailable

With Rack Awareness:
Rack A: Broker 1 (Leader), Broker 2
Rack B: Broker 3 (Follower), Broker 4
Rack C: Broker 5 (Follower), Broker 6

If Rack A fails → Replicas in Rack B and C still available

Configuring Rack Awareness

Broker Configuration

# server.properties on each broker
broker.rack=rack-a

# For AWS availability zones
broker.rack=us-east-1a

# For Kubernetes clusters
broker.rack=zone-1

Topic Creation with Rack Awareness

# Create topic with rack-aware replica placement
kafka-topics.sh \
  --bootstrap-server localhost:9092 \
  --create \
  --topic orders \
  --partitions 6 \
  --replication-factor 3 \
  --config min.insync.replicas=2

# Kafka automatically spreads replicas across racks
# Partition 0: Replicas on [rack-a, rack-b, rack-c]
# Partition 1: Replicas on [rack-b, rack-c, rack-a]
# etc.

Rack Awareness Algorithm

Given:
- 3 racks: [A, B, C]
- 9 brokers: [0,1,2 in A], [3,4,5 in B], [6,7,8 in C]
- Topic with replication factor 3

Kafka's Rack-Aware Assignment:
1. Distribute leader replicas evenly across brokers
2. For each partition, place replicas in different racks
3. Balance replica count per broker

Example Result:
Partition 0: [0(A), 3(B), 6(C)]  ← 3 different racks
Partition 1: [1(A), 4(B), 7(C)]  ← 3 different racks
Partition 2: [2(A), 5(B), 8(C)]  ← 3 different racks

Benefits:

  • ✅ Survives rack/AZ failure
  • ✅ No single point of failure
  • ✅ Higher availability

Trade-offs:

  • ⚠️ Cross-rack replication may increase latency
  • ⚠️ Higher network costs (cross-AZ traffic in cloud)

5. Monitoring Leader Distribution

JMX Metrics

// Key metrics to monitor

// Leaders per broker
kafka.server:type=ReplicaManager,name=LeaderCount

// Partitions per broker (leader + follower)
kafka.server:type=ReplicaManager,name=PartitionCount

// Offline partitions (no leader)
kafka.controller:type=KafkaController,name=OfflinePartitionsCount

// Preferred replica imbalance
kafka.controller:type=KafkaController,name=PreferredReplicaImbalanceCount

Using kafka-topics.sh to Inspect Leaders

# Describe topic to see leader distribution
kafka-topics.sh \
  --bootstrap-server localhost:9092 \
  --describe \
  --topic orders

# Output:
# Topic: orders  Partition: 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
# Topic: orders  Partition: 1  Leader: 2  Replicas: 2,3,1  Isr: 2,3,1
# Topic: orders  Partition: 2  Leader: 3  Replicas: 3,1,2  Isr: 3,1,2

What to Look For:

  • Balanced leaders: Leaders evenly distributed across brokers
  • ISR = Replicas: All replicas in sync
  • Preferred leaders: First replica in list is the current leader

Detecting Imbalance with Scripts

#!/bin/bash
# Check leader distribution across brokers

kafka-topics.sh --bootstrap-server localhost:9092 --describe \
  | awk '/Leader:/ {print $6}' \
  | sort | uniq -c | sort -rn

# Output:
#  45 Leader:1  ← Broker 1 has 45 partitions as leader
#  38 Leader:2  ← Broker 2 has 38 partitions as leader
#  17 Leader:3  ← Broker 3 has 17 partitions as leader (IMBALANCED!)

Imbalance Indicators:

  • Large variance in leader counts
  • Preferred leader ≠ actual leader
  • High PreferredReplicaImbalanceCount metric

Remediation:

  1. Check auto.leader.rebalance.enable=true
  2. Trigger manual preferred leader election:
    kafka-leader-election.sh \
      --bootstrap-server localhost:9092 \
      --election-type PREFERRED \
      --all-topic-partitions
    

6. Tuning Considerations for Large Clusters

Controller Overhead

The Kafka Controller (one broker elected as controller) manages:

  • Partition leadership elections
  • Broker liveness monitoring
  • Metadata propagation

In large clusters:

  • Frequent leader elections overwhelm controller
  • Prefer stability over perfect balance

Tuning Recommendations:

# For clusters > 50 brokers
leader.imbalance.check.interval.ms=600000  # 10 minutes (default: 5 min)
leader.imbalance.per.broker.percentage=15  # More tolerant (default: 10%)
auto.leader.rebalance.enable=true          # Keep enabled but less aggressive

# For clusters > 100 brokers
leader.imbalance.check.interval.ms=900000  # 15 minutes
leader.imbalance.per.broker.percentage=20

Partition Count Limits

Per-Broker Partition Limits:

Cluster Size Recommended Max Partitions per Broker
Small (< 10 brokers) 2,000-4,000
Medium (10-50 brokers) 4,000-6,000
Large (> 50 brokers) 6,000-8,000

Why Limits Exist:

  • Each partition has overhead (file handles, memory, metadata)
  • Controller load increases with partition count
  • Rebalancing takes longer with more partitions

Best Practices:

  • Consolidate low-traffic topics
  • Use fewer partitions for high-throughput topics (contrary to intuition)
  • Monitor controller performance

7. Relationship to Consumer Coordination

Two Levels of Coordination

┌─────────────────────────────────────────────────────┐
│  BROKER-SIDE: Partition Leadership                  │
│  ├─ Which broker leads each partition?              │
│  ├─ Handled by Kafka Controller                     │
│  └─ Affects availability and performance            │
└─────────────────────────────────────────────────────┘
                      ↓
              Partitions exist
                      ↓
┌─────────────────────────────────────────────────────┐
│  CONSUMER-SIDE: Partition Assignment                │
│  ├─ Which consumer reads each partition?            │
│  ├─ Handled by Group Coordinator                    │
│  └─ Affects consumer group throughput                │
└─────────────────────────────────────────────────────┘

Key Differences:

Aspect Broker-Side Consumer-Side
What's assigned Which broker leads partition Which consumer reads partition
Who manages Kafka Controller Group Coordinator
When it changes Leader failure, manual reassignment Consumer join/leave, rebalance
Impact Availability, broker load Consumer throughput, processing distribution

Both Are Independent:

  • Broker leadership can change without affecting consumer assignments
  • Consumer rebalances don't affect broker leadership
  • But both must be healthy for consumers to read data

8. Common Operational Scenarios

Scenario 1: Adding Brokers to Cluster

# 1. Start new broker with unique broker.id
# 2. New broker joins cluster but has no partitions

# 3. Manually reassign partitions to include new broker
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --topics-to-move-json-file topics.json \
  --broker-list "0,1,2,3,4"  ← Include new broker 4
  --generate

# 4. Execute reassignment with throttling
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --execute \
  --throttle 50000000

Scenario 2: Decommissioning a Broker

# 1. Generate reassignment excluding broker to remove
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --topics-to-move-json-file topics.json \
  --broker-list "0,1,2"  ← Exclude broker 3
  --generate

# 2. Execute reassignment
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --execute

# 3. Wait for reassignment to complete
kafka-reassign-partitions.sh \
  --bootstrap-server localhost:9092 \
  --reassignment-json-file reassignment.json \
  --verify

# 4. Shut down broker safely
kafka-server-stop.sh

Scenario 3: Recovering from Leader Imbalance

# 1. Check current leader distribution
kafka-topics.sh --bootstrap-server localhost:9092 --describe \
  | awk '/Leader:/ {print $6}' | sort | uniq -c

# 2. Trigger preferred leader election
kafka-leader-election.sh \
  --bootstrap-server localhost:9092 \
  --election-type PREFERRED \
  --all-topic-partitions

# 3. Verify rebalancing
kafka-topics.sh --bootstrap-server localhost:9092 --describe \
  | awk '/Leader:/ {print $6}' | sort | uniq -c

Summary

You learned:

  • ✅ Partition leadership is managed at the broker level by the Kafka Controller
  • ✅ Preferred leader election automatically rebalances leader distribution
  • ✅ Manual reassignment allows controlled partition movement for scaling and maintenance
  • ✅ Rack awareness improves fault tolerance by spreading replicas across failure domains
  • ✅ Broker-side and consumer-side coordination are independent but complementary
  • ✅ Tuning large clusters requires balancing rebalancing frequency with controller overhead

Key Configurations:

Config Default Purpose
auto.leader.rebalance.enable true Enable automatic leader rebalancing
leader.imbalance.check.interval.ms 300000 Frequency of balance checks
leader.imbalance.per.broker.percentage 10 Imbalance threshold for rebalancing
unclean.leader.election.enable false Allow out-of-sync replicas as leaders
broker.rack (none) Rack/AZ identifier for rack awareness

Next up: Module 3.1 (Partition Assignment Strategies) — Learn how consumers assign partitions among themselves within a group.