DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
Authors: Henry Cai
Status
Current state: "Under Discussion"
Discussion thread: here
JIRA: here [Change the link from KAFKA-1 to your own ticket]
Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).
Motivation
KIP-405 enables Kafka brokers to upload log segments to remote tiered storage, this opens the door to many new use cases, one of them is having consumers to fetch from the tiered storage directly.
Currently, when a new consumer or a fallen-off consumer requires fetching messages from a while ago, and those messages are no longer present in the Kafka broker's local storage, the broker must download the message from the remote tiered storage and subsequently transfer the data back to the consumer. This process involves two data transfers, resulting in increased network latency and transfer costs. Critically, when a broker downloads the data segment from remote storage and stores it locally, it imposes additional IOPS on the network and local disk capacity. Furthermore, this action negatively impacts the page cache established for messages closer to the end of the message queue.
With the data segment file already present on remote tiered storage, there is no reason why the consumer cannot directly fetch them from remote storage without affecting the broker performance. To address this gap, we propose here to allow the consumers to fetch from the remote tiered storage.
This feature will also be highly beneficial for serving large backfill requests from consumer clients from data analytics and streaming applications such as Pinot or Flink.
Proposed Changes
Know the location of remote log segment file
In order to support fetching from the remote tiered storage, the consumer needs to be notified about the location of the remote log segment file for the fetch offset. This can be done either by (1) the consumer subscribes the tiered storage metadata topic: __remote_log_metadata, filters to the partition it interests in, parses each metadata message and tracks the state change; (2) have the leader broker notifies the consumer about the location of the remote log segment file during the consumer FetchRequest/Response message exchange. We recommend the second option: have the leader broker notifies the consumer about the location.
The reason we favor the broker/consumer location exchange is because:
- __remote_log_metaddata topic is a congested topic in tiered storage which contains metadata for all the tiered storage enabled topic partitions and the client also needs to be aware that each metadata needs to go through several state changes. The topic includes the metadata history of all the remote log segment from day 1 even if the segment file itself is already removed from tiered storage; There are lot of reading/filtering and caching needs to happen on the consumer side;
- With many programming languages to support on the consumer side and given the trend of moving complex consumer logic to the broker side, we feel it is more natural to have the broker to keep track of the remote tiered storage segment file and exchange the info with the consumer. This is similar to the design choice (whether consumer or the broker keep tracks of preferred read replica) during KIP-392: Allow consumers to fetch from closest replica design where it also favors to have the broker exchange the preferred read replica information with the consumer.
We propose to extend the Fetch API to convey the remote log segment location information.
The consumer client will initiate the FetchRequest with an extra boolean parameter: RemoteLogSegmentLocationRequested which indicates the client is able to read from remote storage and is interested to get the location of remote log segment file on remote storage. When the leader broker receives FetchRequest from the consumer and it finds out it no longer has the requested fetch offset in the local storage, it can respond with an empty Records and with the extra information about the location of the remote log segment. This is very similar to how KIP-392 responds with empty Records and preferred read replica in FetchResponse to the consumer.
Authorization check
The broker will still perform the standard authorization check against the fetch request.
Fetch and Read Remote Log segment file
Once the consumer is aware of the location of the remote log segment file, it can initiate the read from remote tiered storage and parses the content in log segment file and converts the message into ConsumerRecord objects; We will address them in the follow-up KIP since this work is dependent on the programming language choice on the consumer side.
Public Interfaces
Protocol Changes
We will extend the FetchRequest API by adding a new field RemoteLogSegmentLocationRequested to indicate the client has the capability to read from remote storage and is interested in getting the location of remote log segment file on remote storage.
{
"validVersions": "0-18",
"fields": [
{ "name": "RackId", ... }
{ "name": "RemoteLogSegmentLocationRequested", "type": "bool", "versions": "18+", "default": "false", "ignorable": true,
"about": "Indicate whether the client is able to read from remote storage and interested in getting the location of remote log segment file"}
]
}
We will extend the FetchResponse API in order to convey the location of the remote log segment file to the consumer client.
{
"validVersions": "0-18",
"fields": [
{ "name": "Responses", "type": "[]FetchableTopicResponse", "versions": "0+",
{ "name": "Partitions", "type": "[]PartitionData", "versions": "0+",
{ "name": "PreferredReadReplica", ... },
{ "name": "RemoteLogSegmentId", "type": "uuid", "versions": "18+", "ignorable": true,
"about": "The uuid of the remote log segment id"},
{ "name": "RemoteLogSegmentCustomMetadata", "type": "bytes", "versions": "18+", "ignorable": true,
"about": "The byte[] of the custom metadata of the remote log segment metadata"},
]}
]},
]
}
Two new fields are added to FetchResponse.Partitions message structure:
- RemoteLogSegmentId: this is the uuid field in https://github.com/apache/kafka/blob/4.2/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentId.java#L32
- RemoteLogSegmentCustomMeta: this is the byte[] content in the optional CustomMetadata class in https://github.com/apache/kafka/blob/4.2/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadata.java#L384, some implementations of RemoteStorageManager use this class to store the file path location of the remote log segment file.
These two fields should be sufficient to resolve the physical file path on remote tiered storage.
Compatibility, Deprecation, and Migration Plan
The change is backwards compatible with previous versions. The new parameter RemoteLogSegmentLocationRequested in consumer FetchRequest is false by default to not to change the FetchResponse behavior. And If the receiving broker does not support this feature, it will resort to the old behavior of fetching old messages from remote tiered storage and sending them back to the consumer client.
Rejected Alternatives
- Having the consumer subscribes the tiered storage metadata topic: __remote_log_metadata, filters to the partition it interests in, parses each metadata message and tracks the state change; We don’t recommend this approach because:
- __remote_log_metaddata topic is a congested topic in tiered storage which contains metadata for all the tiered storage enabled topic partitions and each metadata needs to go through several state changes. The topic includes the metadata history of all the remote log segment from day 1 even if the segment file itself is already removed from tiered storage; There are lot of reading/filtering and caching needs to happen on the consumer side;
- With many programming languages to support on the consumer side and given the trend of moving complex consumer logic to the broker side, we feel it is more natural to have the broker to keep track of the remote tiered storage segment file and exchange the info with the consumer. This is similar to the design choice (whether consumer or the broker keep tracks of preferred read replica) during KIP-392: Allow consumers to fetch from closest replica design where it also favors to have the broker exchange the preferred read replica information with the consumer.
- Launch new brokers to serve the large backfill read use cases. When the consumer asks the leader broker to serve FetchRequest, the leader broker will respond with those new brokers' ids in FetchResponse so the consumer will subsequently asks those new brokers to serve FetchRequest. This is very similar to how leader broker responded with preferredReadReplica in KIP-392. Those new brokers can still download log segments from remote storage before they can serve FetchRequest. In this approach, the network latency/cost is not avoided, but we can keep the current running brokers not being affected by reads from large backfill consumers. This approach has minimal code changes needed on the consumer side, but it has the following drawbacks:
- In order not to affect the performance of the current running brokers, we need to group the brokers into different pools (a pool to serve the normal producing/consumer use cases, a pool to serve the backfill or other maintenance tasks), this is a new concept for Kafka community;
- The user needs to manually start/stop those new backfill-dedicated brokers before/after backfill task;
- In order to quickly bootstrap those new brokers to ready-to-serve state, we need KIP-1023: Follower Fetch from tiered offset to be implemented first. With KIP-1023, the new brokers only needs to replicate a few minutes of data from leader broker to be considered in-sync (the rest of the data can be downloaded later lazily from tiered storage);
- Network cost/latency related to 2-hop data transfer (from remote storage to broker, from broker to consumer) is still there.