Walk through the exact configuration needed to enable rack-aware fetch-from-follower, and explain what each setting does.
answer
- broker.rack = AZ label
- replica.selector.class = RackAwareReplicaSelector (broker-side switch)
- client.rack = consumer AZ
- no selector class set = nothing happens
- preferredReadReplica returned in fetch
basics
~20 sOn every broker set broker.rack to its AZ and set replica.selector.class to RackAwareReplicaSelector. On every consumer set client.rack to its own AZ. The broker then matches client.rack to broker.rack and points the consumer at a same-AZ follower.
solid answer
~40 sThree pieces. (1) Broker: broker.rack=<az> tags each broker with its zone; this is also used by the rack-aware replica assignment. (2) Broker: replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector swaps the default LeaderSelector for the rack-aware one — without this, FFF is off and everyone reads the leader. (3) Consumer: client.rack=<az> tells the broker which zone the consumer is in. At fetch time the broker's selector compares client.rack against each in-sync replica's broker.rack and returns a matching follower via preferredReadReplica; the consumer then fetches from it. If no replica matches the rack, the selector falls back to the leader. Note replica.selector.class is a per-broker (cluster-wide) setting and a restart/dynamic update is needed; client.rack is set independently on each consumer and needs no broker change.
code
properties · 6 lines# --- broker (each broker, server.properties) ---
broker.rack=us-east-1a
replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector
# --- consumer (consumer.properties / client config) ---
client.rack=us-east-1ago deeper
Remember there are three knobs and roughly that one is on the consumer (client.rack) and the others on the broker.
Name all three exactly and know which side each lives on; explain the leader fallback.
Discuss dynamic vs static application, custom selectors, and the placement/selection alignment gotcha.
Reason about operational rollout (dynamic config, validating racks across the fleet) and designing a custom selector.
## The three settings, precisely ### 1. `broker.rack` (broker config, static) A string label per broker, conventionally the availability zone, e.g. `broker.rack=us-east-1a`. It already existed pre-KIP-392 for **rack-aware replica assignment** (spreading a partition's replicas across racks/AZs so one AZ failure can't take all copies). KIP-392 reuses it as the locality key for read selection. Every broker should have it set; mixing set and unset racks gives undefined-ish matching. ### 2. `replica.selector.class` (broker config) Names a class implementing `org.apache.kafka.common.replica.ReplicaSelector`. Options: - **Unset / `LeaderSelector` (default):** always returns the leader → classic behavior, FFF disabled. - **`org.apache.kafka.common.replica.RackAwareReplicaSelector`:** returns the in-sync replica whose `broker.rack` matches the requesting client's `client.rack`; falls back to the leader when nothing matches. - **Custom:** you can implement your own selector (e.g., latency-based) — the interface receives `ReplicaView`s and the client metadata and returns the chosen replica. This is a **broker-side** setting. It can be applied as a dynamic cluster config or via restart. If you forget this, setting `client.rack` alone does nothing. ### 3. `client.rack` (consumer config) The consumer advertises its zone, e.g. `client.rack=us-east-1a`. It is sent to the broker, which feeds it into the selector. Set independently per consumer; no broker restart needed. (KafkaConsumer config key is literally `client.rack`.) ## How they interact at fetch time 1. Consumer sends a Fetch including its `client.rack`. 2. Broker invokes `replica.selector.class`'s `select()` with the client metadata and the partition's replica views. 3. `RackAwareReplicaSelector` filters to ISR replicas, prefers one whose `broker.rack == client.rack`, else leader. 4. The chosen replica id is returned to the consumer as the **preferred read replica**; the consumer redirects future fetches for that partition there. 5. The consumer periodically re-checks (the preferred replica can expire, e.g. via `metadata.max.age.ms` style refresh) so it can re-home if leadership/ISR changes. ## Gotchas - Forgetting `replica.selector.class` on the broker is the #1 reason 'nothing happens'. - `broker.rack` must reflect the real AZ; a misconfigured rack sends reads cross-AZ silently (defeats the purpose) — there's no error, just cost. - Rack assignment also affects replica placement; if no replica lives in the consumer's AZ, FFF can't help there — placement and selection must agree. - It's a consumer feature; producers ignore `client.rack` for routing.
- Which of the three settings is most commonly forgotten, and what's the symptom?replica.selector.class on the broker. If it stays at the default LeaderSelector, setting client.rack has zero effect and consumers keep reading the leader — no error, just no savings.
- Is replica.selector.class set per consumer or per broker?Per broker (cluster-wide). client.rack is the per-consumer half; the selector class lives on the brokers.
saying these in an interview costs you the question
- Putting replica.selector.class on the consumer — it's a broker config.
- Thinking client.rack alone enables FFF without the broker selector.
- Believing broker.rack is purely cosmetic — it also drives replica placement.