Kafka源码分享----TransactionCoordinator

总体介绍

transactionCoordinator来协调事务的,在介绍之前先了解几个名词

  • transactionId: 这是应用程序提供的唯一的标识同一个应用程序的id,存储在__transaction_state队列的key为这个transactionId
  • produceId: Kafka为了幂等性引入的,kafka消息是通过produceId来确定是否属于一个事务。
  • produceEpoch: 相同应用不同实例对同一个事务的操作,produceId是一样的,但是produceEpoch是不一样的。

produceEpoch是一个short类型的数,每个事务开始调用的InitProduceId会让其加1,加到最大时会生成一个produceId,但是在事务在Ongoing状态时不会生成新的produceId,在同一个transactionId同一时间下只会有一个produceId,而在新的客户端调用了InitProduceId请求时,旧的客户端则会因为Epoch不同而不能再进行操作。

主要操作是对每一个事务中的消息都会有一个来表示属于同一个事务的操作,transactionCoordinator在事务进行中通过客户端发送的AddPartitionToTxn和AddOffsetsToTxn等请求记录下这个事务操作的topicPartition,这些partitions的数据和这个transactionId对应的状态会存在以__transaction_state为topic的消息队列中。在客户端发送EndTxn的请求时在这些记录的topicPartition发送一个ControlBatch消息来表示这个事务是commit还是Abort。

__transaction_states 的数据

每一个transactionId其对应的状态数据是存储在__transaction_states这个消息队列中,下面图描述了__transaction_states的消息数据的格式。
Kafka源码分享----TransactionCoordinator_第1张图片
__transaction_states的消息key时transactionId表示应用对应的唯一的transactionId,value数据是TxnTransitMetadata,这个数据是TransactionMetadata在队列中的数据。

  • produceId: 这个transactionId所对应的produceId
  • produceEpoch: 这个transactionId所对应的事务epoch
  • txnTimeoutMs: 表示这个事务的运行的最大时间,定时任务会将txnStartTimestamp+txnTimeoutMs
  • TransactionSate: 这个表示当前这个事务的所处状态,是empty,ongoing,prepareCommit,prepareAbort,CompleteCommit,CompleteAbort,Dead,PrepareEpochFence这些状态,在后面会详细描述这个状态机
  • topicPartitions: 这个是存储在这个事务中操作了的所有topicPartition,以让其在EndTxn时向对应的所有的topicPartition发送ControlBatch消息。
  • TxnStartTimestamp: 表示事务开始的时间
  • TxnLastUpdateTimeStamp: 用于对transactionId失效,对长时间没有更新的事务将其数据从__transaction_states中移除数据
  • pendingState: 这是在TransactionMetadata有而TxnTransitMetadata中没有的数据,主要是对应每次对TransactionMestadata的状态切换时,其都会将TransactionMetadata的pendingState设置为将要切换的状态,在真正写入__transaction_states中才将内存状态真正切换为对应的状态。

每次状态迁移时,是先在transactionMetadata中的pendingState设置为目标状态,目标状态数据以TxnTransitMetadata数据形式持久化到__transaction_offsets队列中,持久化完成后再将transactionMetadata中的produceId,produceEpoch,transactionState等数据切换为目标状态。

一个事务的主要流程

下图描述了客户端在一个事务执行中相应的请求。

  1. FindCoordinator: 首先向kafka集群中的一个节点发送一个FindCoordinator找到其对应的TransactionCoordinator所在的broker节点。
  2. InitProduceId: 这个请求时发送到transactionCoordinator,其主要从transactionCoordinator获取对应的transactionId对应的produceId。
  3. 事务正在进行的接口:
    1. AddPartitionsToTxn: 这个请求是在producer生产消息前先要向TransactionCoordinator 发送一个AddParitionToTxn的请求将自己要发送的数据的topicParitition告诉transactionCoordinator
    2. AddOffsetsToTxn: 事务在进行消费位移提交时需要向transactionCoordinator发送AddOffsetsToTxn请求,transactionCoordinator会通过其对应的groupId分析其在__consumer_offsets这个topic中对应的partition,将这个topicPartition加入到__transaction_state中。
    3. TxnOffsetCommit: 这个操作是发向GroupCoordinator,消费者进行位移提交。
    4. Produce: 这个操作是生产者向业务队列生产数据
      4 WriteTxnMarkers: 这个操作是TransactionCoordinator在收到EndTxn请求时会对其记录的所有的TopicPartition写入ControlBatch消息
      Kafka源码分享----TransactionCoordinator_第2张图片

TransactionState状态机

Kafka源码分享----TransactionCoordinator_第3张图片
上图展示了一个transaction的对应的状态机,主要状态有:

  • Empty: 这个状态是刚开始的状态,在接收到InitPorduceId时会切换到这个状态
  • Ongoing: 这个状态是在接收到AddPartitionsToTxn时其对应的状态会从empty,CompleteCommit,CompleteAbort,Ongoing数据切换为Ongoing状态
  • PrepareCommit: 这个状态是在收到EndTxn请求,其为commit时会将状态切换为prepareCommit状态
  • PrepareAbort: 这个状态是收到EndTxn请求时,类型为Abort是其状态会切换为prepareAbort状态
  • CompleteCommit: 这个状态是PrepareCommit下对所有的TopicPartition都成功写入ControlBatch消息时会切换为这个状态。
  • CompleteAbort: 这个状态是PrepareAbort下对所有TopicPartition都成功写入ControlBatch消息会切换到这个状态
  • PrepareEpochFence: 这个状态是在Ongoing状态下收到了InitProduceId的请求时会将其设置为这个状态,并返回一个CONCURRENT_TRANSACTIONS让其重试。transaction不会真正切换到这个状态,是在Ongoing状态下将其pendingState切换为这个状态,然后再立刻切换为PrepareAbort状态。
  • Dead: 这个状态是transactionalId-expiration线程在Empty,CompleteCommit,CompleteAbort状态下长时间没有对应的transactionId的操作会将其对应的transactionId切换为Dead状态

注意: PrepareEpochFence和Dead两个状态TransactionMetadata中的transactionState不会实际转换为这两个状态,只是会存在于其pendingState,并且不会最终写到__transaction_states日志中,过期的transactionId其对应的状态直接是会向队列中加入删除消息,而对于PrepareEpochFence状态是直接切换到PrepareAbort状态

你可能感兴趣的:(kafka)