-
Notifications
You must be signed in to change notification settings - Fork 51
docs: fetch read coalescing (DOC-2386) #1821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Feediver1
wants to merge
8
commits into
beta
Choose a base branch
from
DOC-2386-fetch-read-coalescing
base: beta
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+132
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
652dc16
docs: add fetch read coalescing page (DOC-2386)
Feediver1 d4500fe
docs: apply review feedback on fetch-read-coalescing page
Feediver1 3f9c0ac
docs: single-source fetch-read-coalescing for Redpanda Cloud
Feediver1 8324dec
Replace doc-coined "aligned fan-out" shorthand with plain language
Feediver1 7145bce
Apply suggestion from @Feediver1
Feediver1 8ebd811
Make clear cloud users cannot self-serve enable coalescing
Feediver1 66eed08
Warn that coalescing costs CPU at low fan-out, not just "no benefit"
Feediver1 4b8a22a
Mark fetch read coalescing as an Enterprise feature
Feediver1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
modules/develop/pages/consume-data/fetch-read-coalescing.adoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| = Fetch Read Coalescing | ||
| :description: Reduce redundant read CPU and fetch-response memory under high consumer fan-out by sharing one read result across concurrent fetches of the same data. | ||
| :page-categories: Clients, Development | ||
| // tag::single-source[] | ||
|
|
||
| ifndef::env-cloud[] | ||
| [NOTE] | ||
| ==== | ||
| include::shared:partial$enterprise-license.adoc[] | ||
| ==== | ||
| endif::[] | ||
|
|
||
| When many consumers fetch the same partition at the same offset concurrently (high read fan-out), the broker does redundant work: each fetch performs its own log read, its own serialization, and allocates its own copy of the response bytes. With a fan-out of N consumers, that is roughly N times the read CPU and N times the fetch-response memory for byte-identical output. | ||
|
|
||
| Fetch read coalescing removes that redundancy. The broker reads and serializes each unique read once, and shares the single result with every concurrent (and eligible back-to-back) consumer of the same data: one read, one serialization, one buffer, fanned out to all requesters. When all N consumers fetch the same partition at the same offset with the same fetch settings, read CPU and fetch-response memory drop from roughly N times to one. | ||
|
|
||
| ifdef::env-cloud[] | ||
| Fetch read coalescing is available on BYOC and Dedicated clusters. | ||
|
|
||
| Fetch read coalescing is disabled by default, and the cluster property that controls it is managed by Redpanda; see <<Enable fetch read coalescing>>. It benefits workloads where many consumers tail the same partitions with the same fetch settings, for example fan-out delivery of one stream to many downstream applications. Request it only for high fan-out workloads: at low fan-out (for example, one or two consumers per partition), the de-duplication logic saves little to nothing and its overhead can increase reactor utilization. | ||
| endif::[] | ||
| ifndef::env-cloud[] | ||
| Fetch read coalescing is disabled by default. Enable it when many consumers tail the same partitions with the same fetch settings, for example fan-out delivery of one stream to many downstream applications. Enable it only for high fan-out workloads: at low fan-out (for example, one or two consumers per partition), the de-duplication logic saves little to nothing and its overhead can increase reactor utilization. See <<Evaluate coalescing effectiveness>> for how to measure whether it helps your workload. | ||
| endif::[] | ||
|
|
||
| ifndef::env-cloud[] | ||
| == Prerequisites | ||
|
|
||
| * A valid xref:get-started:licensing/index.adoc[Redpanda Enterprise license]. | ||
| endif::[] | ||
|
|
||
| == How fetch read coalescing works | ||
|
|
||
| The coalescer sits on the fetch read path of each shard and groups reads by the properties that make two reads produce byte-identical output: | ||
|
|
||
| * Partition | ||
| * Fetch offset | ||
| * Isolation level | ||
| * `max_bytes` budget | ||
| * Whether the read is obligatory (guarantees at least one batch and ignores the strict byte limit) or strict (honors `max_bytes`). These are grouped apart, so neither serves the other. | ||
|
|
||
| For each fetch read, one of three things happens: | ||
|
|
||
| * *Ready hit*: A previously completed read is still retained and covers what this fetch needs, so its result is reused with no new read. | ||
| * *In-flight hit*: A read for the same data is already running, so this fetch awaits that read instead of starting its own. | ||
| * *Miss*: The read runs exactly once, and its result is shared with any waiting fetches and retained for later readers. If the read fails, the error is propagated to all waiters. | ||
|
|
||
| The shared result is reference-counted. The coalescer keeps only a weak handle to it, so it never pins memory; the requesting fetches hold the only strong references until their responses are sent. This is where the memory savings come from: coalesced consumers share one buffer instead of each holding its own copy. | ||
|
|
||
| Coalescing is scoped per shard: it collapses only the fan-out that lands on the same shard. It composes with xref:develop:consume-data/follower-fetching.adoc[follower fetching] rather than replacing it: follower fetching spreads consumers across replicas to distribute the read load, and coalescing removes the redundancy within each shard. | ||
|
|
||
| == Enable fetch read coalescing | ||
|
|
||
| ifndef::env-cloud[] | ||
| Enable coalescing with the `kafka_fetch_read_coalescing_enabled` cluster property: | ||
|
|
||
| [,bash] | ||
| ---- | ||
| rpk cluster config set kafka_fetch_read_coalescing_enabled true | ||
| ---- | ||
|
|
||
| This is a runtime change; no restart is required. The coalescing cache is fixed-size (about 0.5 MB per shard) and is allocated only while the feature is enabled; there is no separate sizing property. Setting the property back to `false` disables coalescing and clears the per-shard cache immediately. | ||
| endif::[] | ||
| ifdef::env-cloud[] | ||
| The `kafka_fetch_read_coalescing_enabled` cluster property that controls coalescing is not user-configurable in Redpanda Cloud. To enable coalescing on a BYOC or Dedicated cluster, contact https://support.redpanda.com/hc/en-us/requests/new[Redpanda Support^]. | ||
|
|
||
| Enabling or disabling coalescing is a runtime change: no cluster restart is required, and the coalescing cache (about 0.5 MB per shard) is allocated only while the feature is enabled. | ||
| endif::[] | ||
|
|
||
| ifndef::env-cloud[] | ||
| == Evaluate coalescing effectiveness | ||
|
|
||
| The coalescer exports four counters on the internal `/metrics` endpoint, one series per shard. The metrics are registered only when internal metrics are enabled (that is, when `disable_metrics` is not set). | ||
|
|
||
| |=== | ||
| | Metric | Description | ||
|
|
||
| | `vectorized_kafka_fetch_read_coalescer_insertions_total` | ||
| | Fetch reads that missed and performed a new read. | ||
|
|
||
| | `vectorized_kafka_fetch_read_coalescer_reinsertions_total` | ||
| | Fetch reads that re-read an existing stale or expired entry. | ||
|
|
||
| | `vectorized_kafka_fetch_read_coalescer_ready_hits_total` | ||
| | Fetch reads served from a retained, already-completed read. | ||
|
|
||
| | `vectorized_kafka_fetch_read_coalescer_inflight_hits_total` | ||
| | Fetch reads served by awaiting an in-flight read. | ||
| |=== | ||
|
|
||
| The effectiveness of coalescing is the ratio of hits (reads avoided) to insertions (reads actually performed): | ||
|
|
||
| [.no-copy] | ||
| ---- | ||
| coalescing hit ratio = | ||
| (ready_hits_total + inflight_hits_total) | ||
| / (insertions_total + reinsertions_total + ready_hits_total + inflight_hits_total) | ||
| ---- | ||
|
|
||
| A ratio near 0 means little fan-out is being collapsed: the reads aren't aligning on the same partition, offset, and fetch settings, and the workload is unlikely to benefit from coalescing. A high ratio means the coalescer is absorbing most of the fan-out. | ||
| endif::[] | ||
|
|
||
| == Limitations | ||
|
|
||
|
Feediver1 marked this conversation as resolved.
|
||
| Before enabling fetch read coalescing, familiarize yourself with the following limitations: | ||
|
|
||
| * *Only identical reads coalesce.* Consumers reading the same data but with a different `max_bytes`, a different offset, or a different isolation level do not share a read. The benefit scales with how closely the concurrent fetches match: the ideal case is many consumers tailing the same partition at the same offset with the same fetch sizing. | ||
| * *Obligatory and strict reads are grouped apart.* A single partition and offset fetched both ways at the same time incurs one duplicate read by design. | ||
| * *Retention is best-effort.* Completed results are only reusable by later readers while a fetch still references them; the coalescer never keeps a result alive on its own. The reliable savings are on genuinely concurrent readers of the same data, and back-to-back reuse is opportunistic. | ||
| * *Per-shard scope.* Coalescing collapses only the fan-out that lands on the same shard. Where consumers are spread across replicas and shards, for example with follower fetching, each shard coalesces the fan-out local to it. | ||
| * *De-duplication adds per-read overhead.* The de-duplication logic runs on every fetch read, whether or not reads coalesce. At low fan-out (for example, one or two consumers per partition), this overhead can increase reactor utilization while saving little to nothing, so only enable coalescing for high fan-out workloads. | ||
|
|
||
| == Suggested reading | ||
|
|
||
| * xref:develop:consume-data/follower-fetching.adoc[] | ||
| ifndef::env-cloud[] | ||
| * xref:manage:monitoring.adoc[] | ||
| endif::[] | ||
| ifdef::env-cloud[] | ||
| * xref:manage:monitor-cloud.adoc[] | ||
| endif::[] | ||
|
|
||
| // end::single-source[] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we normally give in-depth details on how a particular feature is implemented in our docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, or at least that is the goal. This is now a standard part of the doc template we feed to Claude, and it creates a consistent experience for users regardless of what feature they are reading about. We found that users wanted/needed more context about features--what is this? What does it do? How do I use it? When should I use it? And how does it work? Of course, we try to keep it fairly high-level.
Are you thinking that this material should not be in the doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine as-is, my only thought is that the way the feature is implement is likely to change more frequently than the intention/goal of the feature. So its something that could become stale in future updates and you folks aren't pinged for any changes outside of
src/v/configAFAIK.