暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

依然KafkaⅥ Exactly-Once

在下uptown 2021-05-23
562

闲聊

说来尴尬,总觉得鸽的时间不长想再放两天假,今天一看竟然鸽了一个多月我丢,感谢那几位在我没有更新的日子里还不忘点广告的盆友,后台看不到是谁,但是你的举手之间我的动力源泉,新文章这不就来了嘛。

今天对我来说是个比较特殊日子,进京城打工整整一年了,一年前这会正兵荒马乱呢,我记得我那车厢里总共也就五六个人,有的口罩恨不得带三层,勒的耳朵通红,当时我就想,人家雷军当年为了拿日本的供应链商顶着辐射危险去日本,咱这也算致敬雷总了。

坐在个靠窗的位置对未来充满了想象,说实话,当时还是很虚的,从来没自己一人跑这么老远,读大学头一天父母还一起陪着呢。路上接了个大学同学的电话,写论文那会没少帮他,还知道慰问一下他老大哥。

一年过得是真快,从学生转变成打工人属实不易,虽然大家都戏称自己人上人,只不过是在面对难以突破的社会阶级面前安慰自己的阿Q思想罢了。我还是时常会梦见读书的日子,读书是真香啊,毕了业之后自己的脾气越来越好,之前咽不下的气老老实实的咽下去,倒是体重略有长进,过年那会我寻思家里称坏了呢,跟我爹一样沉了,这个还是得控制下。

干这行本来就不咋运动,身体还是很重要滴。上周跟之前大学实验室的几个同学吃了波饭,大家还是老样子没啥变化,就是腿哥越来越油腻了。这几周接连好几个同事离职,我们组也走了个,很烦,又少了一个可以互相吐槽的同事。好了不吐槽了,说正事。

Kafka如何实现Exactly-Once

本章是kafka系列的终章,是时候跟它告个别了。大部分问题的答案都能在之前的文章中找到。谜底就在谜面上

Kafka的三种语义

三种语义老生常谈了,在producer推送数据至topic的过程中也可能会遇到网络问题。根据producer处理此类故障所采取的提交策略类型,可以有三种语义:

  • at-least-once:如果producer收到来自Kafka broker的确认(ack)或者acks = all,则表示该消息已经写入到Kafka。但如果producer ack超时或收到错误,则可能会重试发送消息,客户端会认为该消息未写入Kafka。如果broker在发送Ack之前失败,但在消息成功写入Kafka之后,此重试将导致该消息被写入两次,因此消息会被不止一次地传递给最终consumer,这种策略可能导致重复的工作和不正确的结果。
  • at-most-once:如果在ack超时或返回错误时producer不重试,则该消息可能最终不会写入Kafka,因此不会传递给consumer。在大多数情况下,这样做是为了避免重复的可能性,业务上必须接收数据传递可能的丢失。
  • exactly-once:即使producer重试发送消息,消息也会保证最多一次地传递给最终consumer。该语义是最理想的,但也难以实现,这是因为它需要消息系统本身与生产和消费消息的应用程序进行协作。例如如果在消费消息成功后,将Kafka consumer的偏移量rollback,我们将会再次从该偏移量开始接收消息。这表明消息传递系统和客户端应用程序必须配合调整才能实现excactly-once。

保持幂等性

幂等性的操作就是一种被执行多次造成的影响和只执行一次造成的影响一样的操作。如果出现导致生产者重试的错误,同样的消息,仍由同样的生产者发送多次,将只被写到kafka broker的日志中一次。

对于单个分区,幂等生产者不会因为生产者或broker故障而发送多条重复消息。要开启这个特性,获得每个分区内的精确一次语义,有重复,没有丢失,并且有序的语义,只需要设置producer配置中的enable.idempotence=true
。在底层,它和TCP的工作原理有点像,每一批发送到Kafka的消息都将包含一个序列号,broker将使用这个序列号来删除重复的发送,序列号会被持久化到副本日志,所以,即使分区的leader挂了,其他的broker接管了leader,新leader仍可以判断重新发送的是否重复了。

跨分区事务

事务大家都知道,一系列操作要么都成功,要么都失败,Kafka现在通过新的事务API支持跨分区原子写入。允许一个生产者发送一批到不同分区的消息,这些消息要么全部对任何一个消费者可见,要么对任何一个消费者都不可见。这个特性也允许在一个事务中处理消费数据和提交消费偏移量,从而实现端到端的精确一次语义。下面是的代码片段演示了事务API的使用:

producer.initTransactions();
try {
    producer.beginTransaction();
    producer.send(record1);
    producer.send(record2);
    producer.commitTransaction();
} catch(ProducerFencedException e) {
    producer.close();
} catch(KafkaException e) {
    producer.abortTransaction();
}

这个感觉知道有事务这回事就好了,毕竟我们都是API调用攻城狮,到时候现用现查就好。好了,这一套kafka连招下来虽然不能登峰造极,指点指点群里的小老弟还是没啥问题的

这周末公司团建,看下有没有时间更一波,最近得想想下个系列更啥,下期见了~


文章转载自在下uptown,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论