Kafka 事务特性分析

kafka transaction Kafka 事务特性分析


1、特性背景

支持事务消息有什么作用?

      消息事务是实现分布式事务的一种方案,可以确保分布式场景下的数据最终一致性。

 

2、分布式事务介绍

当前系统架构主流是分布式架构微服务架构

      在这种架构下数据源不是单一的数据库,业务逻辑往往需要在多个数据库中实现原子操作,单个数据库中的强大的本地事务无法保证多节点原子操作。

 

3、Kafka事务的使用

Kafka中的事务特性主要用于以下两种场景:

(1)生产者发送多条消息可以封装在一个事务中,形成一个原子操作。多条消息要么都发送成功,要么都发送失败。

(2)read-process-write模式:将消息消费和生产封装在一个事务中,形成一个原子操作。在一个流式处理的应用中,常常一个服务需要从上游接收消息,然后经过处理后送达到下游,这就对应着消息的消费和生成。

注:当事务中仅仅存在Consumer消费消息的操作时,它和Consumer手动提交Offset并没有区别。因此单纯的消费消息并不是Kafka引入事务机制的原因,单纯的消费消息也没有必要存在于一个事务中。

 

4、Kafka事务原理

Kafka为了支持事务特性,引入一个新的组件:Transaction Coordinator。主要负责分配pid,记录事务状态等操作。

下面Kafka开启一个事务到提交一个事务的流程图:

Kafka 事务特性分析_第1张图片

 

主要分为以下步骤:

1.  查找Tranaction Corordinator

Producer向任意一个brokers发送 FindCoordinatorRequest请求来获取Transaction Coordinator的地址。

2.  初始化事务 initTransaction

Producer发送InitpidRequest给Transaction Coordinator,获取pid。Transaction Coordinator在Transaciton Log中记录这的映射关系。另外,它还会做两件事:

(1)恢复(Commit或Abort)之前的Producer未完成的事务

(2)对PID对应的epoch进行递增,这样可以保证同一个app的不同实例对应的PID是一样,而epoch是不同的。

注:只要开启了幂等特性即必须执行InitpidRequest,而无须考虑该Producer是否开启了事务特性。

3.  开始事务beginTransaction

执行Producer的beginTransacion(),它的作用是Producer在本地记录下这个transaction的状态为开始状态。这个操作并没有通知Transaction Coordinator,因为Transaction Coordinator只有在Producer发送第一条消息后才认为事务已经开启。

4.  read-process-write流程

一旦Producer开始发送消息,Transaction Coordinator会将该存于Transaction Log内,并将其状态置为BEGIN。另外,如果该为该事务中第一个,Transaction Coordinator还会启动对该事务的计时(每个事务都有自己的超时时间)。

在注册到Transaction Log后,生产者发送数据,虽然没有还没有执行commit或者abort,但是此时消息已经保存到Broker上了。即使后面执行abort,消息也不会删除,只是更改状态字段标识消息为abort状态。

5.  事务提交或终结 commitTransaction/abortTransaction

在Producer执行commitTransaction/abortTransaction时,Transaction Coordinator会执行一个两阶段提交:

  • 第一阶段,将Transaction Log内的该事务状态设置为PREPARE_COMMITPREPARE_ABORT
  • 第二阶段,将Transaction Marker写入该事务涉及到的所有消息(即将消息标记为committedaborted)。这一步骤Transaction Coordinator会发送给当前事务涉及到的每个<Topic, Partition>的LeaderBroker收到该请求后,会将对应的Transaction Marker控制信息写入日志。

一旦Transaction Marker写入完成,Transaction Coordinator会将最终的COMPLETE_COMMITCOMPLETE_ABORT状态写入Transaction Log中以标明该事务结束。

 

5、总结

      Transaction Marker与PID提供了识别消息是否应该被读取的能力,从而实现了事务的隔离性。

      Offset的更新标记了消息是否被读取,从而将对读操作的事务处理转换成了对写(Offset)操作的事务处理。

      Kafka事务的本质是,将一组写操作(如果有)对应的消息与一组读操作(如果有)对应的Offset的更新进行同样的标记(Transaction Marker)来实现事务中涉及的所有读写操作同时对外可见或同时对外不可见。

      Kafka只提供对Kafka本身的读写操作的事务性,不提供包含外部系统的事务性。

 


      加油!

你可能感兴趣的:(Kafka)