关于kafka事务的一些理解

kafka的事务机制,主要是为了保证

  • 可回滚操作
  • 确保exactly once
  • 原子性

Exactly Once

实际上,除了一些利用其它第三方中间件和GUID的情况,我们也可以使用kafka的事务来实现exactly once。主要方法是让下游系统通过具备幂等性,借用at least once的基本语意来实现,消费且仅一次,但是也是有限制条件的,如下:

  • 要求下游系统必须具有幂等性
  • 实现需要对kafka的工作机制很了解
  • 对于kafka stream而言,kafka本身就是自己的下游系统,但是他自己本身0.11之前不支持幂等操作。

操作原子性

目的在于

  • 提高数据的一致性,要不成,要不GG
  • 因为是原子操作,所以不需要关注中间状态,知道结果就可以了

幂等性发送

在这里说一下kafka是如何做到的幂等性发送。

之前说了,为了实现kafka的exactly once,就要上下游系统实现幂等性,但是对于kafka Stream来说kafka Producer本身就是下游,所以就来说一下kafka的系统设计方法。

为了实现 Producer 的幂等语义,Kafka 引入了Producer ID(即PID)和Sequence Number。每个新的 Producer 在初始化的时候会被分配一个唯一的 Producer ID,该 Producer ID 对用户完全透明而不会暴露给用户。

而对于每一个Producer ID发送的<Topic , Partition> 都对应一个从0开始计数的Sequence number。

同样的,broker端也会维护一个< PID , Topic , Partition>序号,每次commit的时候,这个对应的序号就会+1,对于接收的每条消息,如果其维护的序号比brokerID大1,就可以接收,不然就丢弃。

但是这个只能针对单个producer对于同一个<Topic,Partition>的Exactly once情况,这是无法保证写操作的原子性的,也就是无法保证多个写操作的原子性和读写操作的原子性,也就是要么全部成功,要么全部失败。

所以就得通过事务来实现。

事务性保证多写原子性

首先需要客户端提供一个Transaction ID,Transaction ID会和Producer Id一一对应,区别就是Producer Id是由自己内部生成的。

而Transaction Id的主要作用如下:

  • 跨Session的数据幂等发送:当具有相同的TransactionId的Producer实例被创建的时候,旧的就不工作了。
  • 跨Session的的事务恢复:当一个应用宕机了,当前Producer可以保证立刻commit或者abort,从而保证不会影响后面的Producer。

但是Consumer那边就不一样了,会有一些问题:

  • 事务的具体内容可能分布在多个Segment,如果删了一个,可能会导致部分事务失效
  • Consumer可能不会消费整个partition的消息,所以如果在多个Segment,可能就会无法知道全部事务。

事务中的offset提交

在疏漏总结也说过关于at least once和at most once的触发条件了,现在说一下通过事务是如何进行实现的。

首先我们知道,kafka的Stream中,producer负责处理完数据扔进topic处理,consumer负责拉取数据消费。为了能保证原子性,我们就必须让producer commit和consumer commit在一个事务内去实现,不然就会造成一些数据问题。

  • 如果先处理producer的commit,就会导致at least once,也就是消息会发送重复。
  • 如果先处理consumer的commit,就会导致at most once,也就是消息会少发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值