Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This page is meant as a template for writing a KIP. To create a KIP choose Tools->Copy on this page and modify with your content and replace the heading with the next KIP number and a description of your issue. Replace anything in italics with your own description.

Status

Current state: Under Discussion

...

Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).

Motivation


Share Groups currently support only immediate acknowledgement modes (IMPLICIT/EXPLICIT). This causes data loss in distributed streaming frameworks:

...

We will be following the similar existing pattern we have in Kafka Producer Transactions.

Use Cases

- Apache Flink: Exactly-once checkpointing with Share Group sources
Apache Spark: Structured Streaming with Share Group consumers
Any coordinator-worker streaming framework requiring atomic acknowledgements

Public Interfaces

APIs 

  • KafkaProducer.sendShareAcksToTransaction(acks, groupId) - for CTP 
    • This mirrors the existing KafkaProducer.sendOffsetsToTransaction(offsets, groupMetadata)

...

// TransactionalShareAcknowledger — internally just wraps a KafkaProducer 
TransactionalShareAcknowledger acknowledger = 
    new TransactionalShareAcknowledger(config);  // config has transactional.id
acknowledger.initTransactions();
acknowledger.commitAcknowledgements(acks, shareGroupId);  // begin+ack+commit in one call

```

Coordinator API

  • Reuses the existing TransactionCoordinator
  • new server-side component is a completeTransaction() method on ShareCoordinator, mirroring GroupCoordinator.completeTransaction().
  • WriteTxnMarkers as the mechanism for the transaction coordinator to tell the group coordinator to complete transactional operations on __consumer_offsets
    • For consumer group we have => groupCoordinator.completeTransaction(partition, ...)
    • Similarly implement shareCoordinator.completeTransaction(partition, ...) for share group 

New Metrics

Metric                                Type        Description
share-transaction-active              Gauge       Active transactions
share-transaction-prepare-time-ms     Histogram   Prepare latency
share-transaction-commit-time-ms      Histogram   Commit latency
share-transaction-abort-total         Counter     Aborted transactions
share-transaction-timeout-total       Counter     Timed-out transactions

Proposed Changes

1. Two-Phase Commit Protocol

Transaction States Transitions

existing Kafka 2PC (TransactionState: ONGOING→PREPARE_COMMIT→COMPLETE_COMMIT)

...

- EMPTY -> ONGOING -> ABORTED (early abort)

Sequence Diagram





Abort case: 




This KIP reuses Kafka's existing two-phase commit protocol:

...

existing TransactionCoordinator recovery

2. Wire Protocol Details

TxnShareAcknowledgeRequest

```
ShareAcknowledgeTransactionalRequest => GroupId TransactionId [Topics]
  GroupId => STRING
  TransactionId => STRING
  Topics => TopicId [Partitions]
    Partitions => Partition [AcknowledgementBatches]
      AcknowledgementBatches => FirstOffset LastOffset AcknowledgeType
```

ShareBeginTransactionRequest

Use existing InitProducerIdRequest

SharePrepareTransactionRequest

 Use existing EndTxnRequest

ShareCommitTransactionRequest / ShareAbortTransactionRequest

Handled by existing WriteTxnMarkersRequest (inter-broker) and  EndTxnRequest(ABORT)

AddShareAcksToTxnRequest

  • mirrors AddOffsetsToTxnRequest; This tells the TransactionCoordinator to add __share_group_state partitions to the producer's transaction.
  • AddShareAcksToTxn computes TopicPartition(SHARE_GROUP_STATE_TOPIC_NAME, shareCoordinator.partitionFor(shareGroupId, topicPartition)) and  adds it to the producer's TransactionMetadata.topicPartitions set via TransactionCoordinator.handleAddPartitionsToTransaction().
  • This is what causes WriteTxnMarkers to dispatch markers to __share_group_state partitions during commit.

...

    Partitions => INT32

```

Consume-Transform-Produce Pattern

This is the exactly-once guarantee: either both output AND acks commit, or neither does: 

...

  • Output records get ABORT markers -> consumers with read_committed skip them
  • Share acks are discarded -> records stay ACQUIRED -> acquisition lock timeout -> records return to AVAILABLE -> re-delivered to another consumer

no-producer (Flink/Spark) use case 

```

// Flink ShareGroupSource connector — on checkpoint complete

...

        acknowledger.commitAcknowledgements(pendingAcks, shareGroupId);

    }

}

```

Compatibility, Deprecation, and Migration Plan

Impact on Existing Users

- No breaking changes for existing Share Group users
- `transactional` mode is opt-in via `share.acknowledgement.mode` config
- Existing `implicit` and `explicit` modes continue to work unchanged

Migration Path

1. Phase 1: Add `transactional` acknowledgement mode (backward compatible)
2. Phase 2: Streaming frameworks (Flink, Spark) implement transactional sources
3. Phase 3: Documentation and best practices for exactly-once semantics

Deprecation

- No deprecation of existing modes planned
- `transactional` mode recommended for exactly-once use cases

Test Plan

Unit Tests

- Transaction state machine transitions
- Idempotency of all transaction operations
- Timeout handling and auto-abort
- Record state transitions (ACQUIRED → ACKNOWLEDGED on commit, ACQUIRED → AVAILABLE on abort/timeout)

Integration Tests

- End-to-end transaction commit/abort flows
- Multi-consumer transactions within same group
- Coordinator failure and recovery
- Network partition scenarios

System Tests

- Flink checkpoint integration with transactional Share Groups
- Exactly-once delivery verification under failures
- Performance benchmarks comparing transactional vs non-transactional modes
- Stress testing with concurrent transactions

Chaos Tests

- Broker failure during PREPARE state
- Coordinator crash before/after prepare
- Consumer crash during transaction
- Network partitions between coordinator and brokers

Rejected Alternatives

If there are alternative ways of accomplishing the same thing, what were they? The purpose of this section is to motivate why the design is the way it is and not some other way.