kafka怎么保证数据消费一次且仅消费一次?

Spark-Streaming获取kafka数据的两种消费模式、三种消费语义 两种消费模式 一、基于Receiver的方式 Receiver是使用Kafka的高层次Consumer API来实现的。receiver从Kafka中获取的数据都是存储在Spark Executor的内存中的,然后Spark Streaming启动的job会去处理那些数据。 然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据。如果要启用高可靠机制,让数据... 阅读详情

 

1.众所周知,kafka0.11.0.0版本正式支持精确一次处理语义(exactly onece semantic–EOS),Kafka的EOS主要体现在3个方面:

1)幂等producer 保证单个分区的只会发送一次,不会出现重复消息
2)事务(transation):保证原子性的写入多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚
3)流式EOS:流处理本质上可看成是“”读取-处理-写入的管道“”。此EOS保证整个过程的操作是原子性。注意,只使用kafka Streams

上面3中EOS语义有着不同的应用范围,幂等producer只能保证单分区上无重复消息;事务可以保证多分区写入消息的完整性;而流处理EOS保证的是端到端(E2E)消息处理的EOS。用户在使用过程中需要根据自己的需求选择不同的EOS。
以下是启用方法:
1)启用幂等producer:在producer程序中设置属性enabled.idempotence=true,但不要设置transational_id.注意是不要设置,而不是设置为空字符串。

2)启用事务支持:在producer程序中设置属性transcational.id为一个指定字符串(你可以认为这是你的额事务名称,故最好七个有意义的名字),同时设置enable.idempotence=true

3)启用流处理EOS:在Kafka Streams程序中设置processing.guarantee=exactly_once

2.关于幂等producer的一些讨论

所谓幂等producer指producer.send的逻辑是幂等的,即发送相同的Kafka消息,broker端不会重复写入消息。同一条消息Kafka保证底层日志中只会持久化一次,既不会丢失也不会重复。幂等性可以极大地减轻下游consumer系统实现消息去重的工作负担,因此是非常实用的功能。值得注意的是,幂等producer提供的语义保证是有条件的:

单分区幂等性:幂等producer无法实现多分区上的幂等性。如前所述,若要实现多分区上的原子性,需要引入事务。

单会话幂等性:幂等producer无法跨会话实现幂等性。即使同一个producer宕机并重启也无法保证消息的EOS语义

虽然有上面两个限制,幂等producer依然是一个非常实用的新功能。下面我们来讨论下它的设计原理。如果要实现幂等性, 通常都需要花费额外的空间来保存状态以执行消息去重。Kafka的幂等producer整体上也是这样的思想。

首先,producer对象引入了一个新的字段:Producer ID(下称PID),它唯一标识一个producer,当producer启动时Kafka会为每个producer分配一个PID(64位整数),因此PID的生成和分配对用户来说是完全透明的,用户无需考虑PID的事情,甚至都感受不到PID的存在。其次,0.11 Kafka重构了消息格式(有兴趣的参见Kafka 0.11消息设计),引入了序列号字段(sequence number,下称seq number)来标识某个PID producer发送的消息。和consumer端的offset类似,seq number从0开始计数并严格单调增加。同时在broker端会为每个PID(即每个producer)保存该producer发送过来的消息batch的某些元信息,比如PID信息、消息batch的起始seq number及结束seq number等。这样每当该PID发送新的消息batch时,Kafka broker就会对比这些信息,如果发生冲突(比如起始seq number和结束seq number与当前缓存的相同),那么broker就会拒绝这次写入请求。倘若没有冲突,那么broker端就会更新这部分缓存然后再开始写入消息。
这就是Kafka实现幂等producer的设计思路:
  1. 为每个producer设置唯一的PID;
  2. 引入seq number以及broker端seq number缓存更新机制来去重。

介绍了设计思想,我们来看下具体的实现,如下图所示:
在这里插入图片描述

Java producer(区别于Scala producer)是双线程的设计,分为KafkaProducer用户主线程和Sender线程。前者调用send方法将消息写入到producer的内存缓冲区中,即RecordAccumulator中,而后者会定期地从RecordAccumulator中获取消息并将消息归入不同的batch中发送到对应的broker上。在幂等producer中,用户主线程的逻辑变动不大。send方法依然是将消息写入到RecordAccumulator。而Sender线程却有着很大的改动。我们首先来看下上图中的第一步:发送InitProducerIdRequest请求。

InitProducerIdRequest是0.11.0.0版本新引入的请求类型,它由两个字段组成:transactionalId和timeout,其中transactionalId就是producer端参数transactional.Id的值,timeout则是事务的超时时间。由于我们未引入事务而只是配置幂等producer,故transcationalId为null,而timeout则设置成了Int.MAX,即Sender线程将一直阻塞直到broker端发送PID返回。一旦接收到broker端返回的response,Sender线程就会更新该producer的PID字段。有兴趣的读者可以参考源码:Sender.maybeWaitForProducerId,如下图所示:在这里插入图片描述

下面我就不贴源码了,但会给出对应的源码文件,有兴趣的直接看吧~~)

上图中, 第一步是随机寻找一个负载最低的broker,即当前未完成请求数最少的broker。由此可见,InitProducerIdRequest和MetadataRequest一样,都可由任意的broker完成处理。至于为什么我们稍后讨论,现在先来讨论下broker端是如何确定PID的。其实说起来很简单,Kafka在Zookeeper中新引入了一个节点:/latest_producer_id_block,broker启动时提前预分配一段PID,当前是0~999,即提前分配出1000个PID来,如下图所示:

[zk: localhost:2181(CONNECTED) 2] get /latest_producer_id_block
{"version":1,"broker":0,"block_start":"0","block_end":"999"}
  • 1
  • 2

一旦PID超过了999,则目前会按照1000的步长重新分配,到时候就应该是这个样子:

{“version”:1, “broker”:0,“block_start”:“1000”,“block_end”:“1999”}

除了上面的信息,broker在内存中还保存了下一个待分配的PID。这样,当broker端接收到InitProducerIdRequest请求后,它会比较下一个PID是否在当前预分配的PID范围:若是则直接返回;否则再次预分配下一批的PID。现在我们来讨论下为什么这个请求所有broker都能响应——原因就在于集群中所有broker启动时都会启动一个叫TransactionCoordinator的组件,该组件能够执行预分配PID块和分配PID的工作,而所有broker都使用/latest_producer_id_block节点来保存PID块,因此任意一个broker都能响应这个请求。

上图中的第二步就是发送InitProducerIdRequest的方法,注意当前是同步等待返回结果,即Sender线程会无限阻塞直到broker端返回response(当然依然会受制于request.timeout.ms参数的影响)。当拿到response后,Sender线程就会更新该producer的PID字段,如图中第三步所示。

确定了PID之后,Sender线程会调用RecordAccumulator.drain()提取当前可发送的消息,在该方法中会将PID,Seq number等信息封装进消息batch中,具体代码参见:RecordAccumulator.java#drain()。一旦获取到消息batch后,Sender线程开始构建ProduceRequest请求然后发送给broker端。至此producer端的工作就算告一段落了。

下面我们看下broker端是如何响应PRODUCE请求。实际上,broker最重要的事情就是要区别某个PID的同一个消息batch是否重复发送了。因此在消息被写入到leader底层日志之前必须要先做一次判断,即PRODUCE请求中的消息batch是否已然被处理过,判断的逻辑就在:ProducerStateManager.scala中的ProducerAppendInfo#validateAppend方法中。如果请求中包含的消息batch与最近一次成功写入的batch相同(即PID相同,batch起始seq number和batch结束seq number都相同),那么该方法便抛出DuplicateSequenceNumberException,然后由上层方法捕获到该异常封装进ProduceResponse返回。如果batch不相同,则允许此次写入,并在写入完成后更新这些producer信息。

值得一提的是在0.11.0.0版本中DuplicateSequenceNumberException继承自RetriableException类,即表示Kafka认为它是一个可重试的异常。这其实是个问题,因为抛出该异常已经表明broker不需要处理这次写入,即使重试broker依然会拒绝,因此在1.0.0版本中该类已经不再继承自RetriableException,顺便还改了个名字:DuplicateSequenceException。

以上就是关于幂等producer的一些讨论。从上面的分析中我们可以看到幂等producer的设计思想主要是基于用空间保存状态并利用状态来去重的思想。了解了这一点,你会发现幂等producer的设计以及代码改动实际上非常容易理解。

最后再说一点:以上所说的幂等producer一直强调的是“精确处理一次”的语义,实际上幂等producer还有“不乱序”的强语义保证,只不过在0.11版本中这种不乱序主要是通过设置enable.idempotence=true时强行将max.in.flight.requests.per.connection设置成1来实现的。这种实现虽然保证了消息不乱序,但也在某种程度上降低了producer的TPS。据我所知,这个问题将在1.0.0版本中已然得到解决。在后续的Kafka 1.0.0版本中即使启用了幂等producer也能维持max.in.flight.requests.per.connection > 1,具体的算法我还没有看,不过总之是个好消息。至于表现如何就让我们拭目以待吧~~

转自http://www.mamicode.com/info-detail-2058306.html

如何保证Kafka有且仅消费一次? Kafka的几个核心的概念: Producer:生产message发送到topic Consumer:订阅topic消费message,Consumer作为一个线程来进行消费 Consumer Group:一个Consumer Group包含多个Consumer,这个预先在配置文件中配置 Broker:一个Kafka节点就是一个Broker,多个Broker组成Kafka集群 Topic:一类消息... 阅读详情

相关推荐

kafka学习总结(处理多个consumer只消费topic数据一次)

最近遇到一个问题,由于kafka接收数据进行处理所花费的时间较长,导致kafka队列中有堆积,然后就想开启很多个consumer但是不怎么会用,报了一些错误,通过一天的学习了解,终于可以让多个consumer共同消费topic中的数据了。使用3个producer同时对一个topic写入数据,其中使用2个group组来对数据进行读取,其中topic中的partitions定为2。在每个group下又创

zhaishujie的博客 3万+

实现Kafka至少消费一次

在实际重要的场景中,常常需要实现消费者至少消费一次。因为使用默认的kafka消费者存在某些问题。

sky的博客 2167

Kafka分区数据消费:实现指定分区数据的消费

每个分区中的数据可以被多个消费者(consumers)并行地消费,这使得Kafka具备了高吞吐量和可伸缩性的特点。综上所述,通过配置Kafka消费者、订阅指定分区和消费数据的方式,我们可以实现对指定分区数据的消费。在本例中,我们简单地打印出了消费到的消息的键、值、偏移量和分区信息。在配置中,我们指定了Kafka集群的地址和端口、消费者组的ID,以及用于反序列化键和值的反序列化器。在示例中,我们订阅了名为"my-topic"的主题中的第一个分区(分区编号为0)。需要注意的是,上述示例仅消费了指定分区的数据。

YazIdris的博客 788

kafka保证精确一次消费

一、消息传递语义: 三种,至少一次,至多一次,精确一次 1、at lest once:消息不丢,但可能重复 2、at most once:消息会丢,但不会重复 3、Exactly Once:消息不丢,也不重复。 保证消息不丢、消息不重复 消息不丢:副本机制+ack,可以保证消息不丢。 数据重复:brocker保存了消息之后,在发送ack之前宕机了,producer认为消息没有发送成功进行重试,导致数据重复。 数据乱序:前一条消息发送失败,后一条消息发送成功,前一条又重试,成功了,导致数据乱.

m0_61607827的博客 4505

TVS 和压敏电阻联合使用进行浪涌保护时,压敏电阻的压敏电压要低于TVS 的钳位电压 VC。

通过先让MOV接管,可以确保在大多数情况下,电压不会迅速上升到TVS二极管的钳位电压,从而保护TVS二极管免受持续高能量冲击的损害。总结来说,将MOV的压敏电压设置得低于TVS二极管的钳位电压,可以提供一种分级的保护机制,优化浪涌保护性能,同时保护敏感的TVS二极管不被过度的能量冲击损坏,并延长其使用寿命。MOV吸收的能量(Wmov):假设浪涌电流为10kA,MOV导通后将电压限制在300V,那么Wmov = Ipp * Vmov = 10kA * 300V = 3MW。例如,Vmov可以设定为275V。

weixin_66642980的博客 2248

长短期记忆网络(Long Short-Term Memory networks, LSTM)

如何简单的理解LSTM——其实没有那么复杂:

weixin_39910711的博客 2万+

kafka怎么保证数据消费一次且仅消费一次?使用消息队列如何保证幂等性?

精确一次处理语义(exactly onece semantic–EOS),Kafka的EOS主要体现在3个方面:1)幂等producer 保证单个分区的只会发送一次,不会出现重复消息2)事务(transation):保证原子性的写入多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚3)流式EOS:流处理本质上可看成是“读取-处理-写入管道”。整个过程的操作是原子性。幂等produc...

AI天才研究院 1万+

用Charles抓包调试iOS应用?这份保姆级配置指南帮你绕过所有坑

本文提供了一份在Mac上使用Charles抓包调试iOS应用的保姆级配置指南。详细讲解了从Charles安装、Mac端代理设置、根证书安装,到iOS设备连接同一WiFi、配置代理以及最关键的系统证书信任等全流程步骤,并分享了SSL代理规则、断点调试等进阶技巧,帮助开发者高效定位和解决网络请求问题。

rice5的博客 640

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?...

1、kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功 消息重复解决方案: 消息可以使用唯一id标识 生产者(ack=all 代表至少成功发送一次) 消费者 (offset手动提交,业务...

weixin_30722589的博客 1195

FID指标实战:如何用Python快速计算生成图像的质量分数(附完整代码)

本文详细介绍了如何使用Python计算Fréchet Inception Distance(FID)指标,以评估生成图像的质量。通过完整的代码示例和优化技巧,帮助开发者快速实现FID计算,并解读分数背后的实际意义,适用于GAN和扩散模型的性能评估。

weixin_28718487的博客 377

CATIA二次开发——遍历几何图形集下的轴系及控制轴系生成位置

CATIA二次开发——轴系相关问题1.遍历几何图形集下的轴系2.解决轴系生成位置的问题 1.遍历几何图形集下的轴系 近期遇到的问题:遍历轴系的时候发现,AxisSystem属性的轴系只有放在轴系集合下,才能被找到,放在几何图形集或其他位置均不能被找到。本来想遍历几何图形集下的轴系元素,但是发现没有对应的属性,只能查找 几何图形集、几何元素、草图等元素,无法直接遍历轴系。 解决办法:(加入选择集,在选择集中筛选轴系类型) HybridBody axisHB = activePart.HybridBodies

WorkMan的博客 2731

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性? 1、kafka在高并发的情况下,如何避免消息丢失和消息重复?消息丢失解决方案:首先对kafka进行限速,其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功消息重复解决方案:消息可...

chw65897的博客 885

PyTorch视觉项目实战:从数据加载到模型部署

PyTorch视觉项目实战:从数据加载到模型部署 ,人工智能,计算机视觉,大模型,AI,随着深度学习在计算机视觉领域的飞速发展,PyTorch 凭借其简洁的代码风格、动态计算图特性以及强大的社区支持,成为众多开发者和研究人员的首选框架。从数据加载、模型构建与训练,到最终的模型部署,PyTorch 提供了一套完整且灵活的解决方案。本文将通过实际项目案例,详细阐述基于 PyTorch 的视觉项目全流程,结合丰富的代码示例和概念解析,帮助读者掌握从项目起步到落地的关键技术。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 4万+

Kafka数据问题

1、kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功 消息重复解决方案: 消息可以使用唯一id标识 生产者(ack=all 代表至少成功发送一次) 消费者 (offset手动提交,业务逻辑成功处理后,...

沧海一粟的博客 292

基于点云数据的统计滤波算法改进

随着三维视觉和点云处理技术的发展,点云数据在机器人、自动驾驶、增强现实等领域得到了广泛应用。而点云数据中常常包含着各种噪声和异常点,这些噪声和异常点会影响后续的数据处理和分析任务。因此,对点云数据进行滤波处理是必不可少的一步。在点云滤波算法中,统计滤波(Statistical Filtering)是一种常见且有效的方法。它通过对点云数据进行统计分析,将噪声和异常点剔除或修复,从而得到更为准确和可靠的点云数据。本文将介绍一种改进的统计滤波算法,并提供相应的源代码实现。

QfcaLinux的博客 292

库存管理系统项目部署方案(基于jdk8)

不需要安装到服务器,运维本地安装就行,主要是用来编译前端代码的。构建完成后将dist文件夹复制到服务器内。

程序员诚哥 2577

sparkstreaming读取kafka消息的两种方式

sparkstreaming 消费kafka数据的 kafkautil 提供两种创建dstream的方法: 1 老版本的createStream方法 2 新版本的createDirectStream方法 通过createDirectStream方法创建出来的dstream的rdd partition 和 kafka 的topic的partition是一一对应的,通过低阶API直接从kafka的topic消费消息,并行计算效率高,默认将偏移...

大块白云的博客 1217

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

sparkstreaming消费kafka如何保证输出结果只会产生一次?(事务性)

最近开始使用sparkstreaming+kafka0.10,使用过程中碰到问题:    steaming采用的direct方式 ,(这种方式和receiver方式的对比性能会好很多),spark计算完数据之后有一个结果入库操作,现在问题来了,采用自动提交的时候程序二次启动经常会出现重复消费的情况,并且怎么保证这个结果只生产一次呢?首先介绍一下sparkstreaming内部是怎么做到消息只计算一...

u013314600的博客 4584

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

kafka如何保证数据的顺序消费

在对kafka的理解中,常常会被问及到kafka如何保证数据的顺序消费、kafka的数据重复消费怎么处理、如何保证kafka中数据不丢失?今天先说说数据的顺序消费问题。 关于顺序消费的几点说明: ①、kafka的顺序消息仅仅是通过partitionKey,将某类消息写入同一个partition,一个partition只能对应一个消费线程,以保证数据有序。 ②、除了发送消息需要指定partition...

QvQ 4万+

Kafka Consumer如何实现精确一次消费数据

文章目录简介kafka消费机制精确一次消费实现总结 简介 kafka消费机制 精确一次消费实现 总结

qq_18581221的博客 2万+

Spark消费Kafka如何实现精准一次性消费?

1.定义 精确一次消费(Exactly-once) 是指消息一定会被处理且只会被处理一次。不多不少就一次处理。 如果达不到精确一次消费,可能会达到另外两种情况: 至少一次消费(at least once),主要是保证数据不会丢失,但有可能存在数据重复问题。 最多一次消费 (at most once),主要是保证数据不会重复,但有可能存在数据丢失问题。 如果同时解决了数据丢失和数据重复的问题,那么就实现了精确一次消费的语义了。 2. 问题如何产生 数据何时会丢失: 比如实时计算任务进行计算.

鄙人王道长的博客 3979

Kafka+SparkStreaming的精准一次性消费

Kafka+SparkStreaming的精准一次性消费语义Kafka自身的精准一次性ackat least once+幂等性 = exactly oncekafka事务SparkStreaming exactly onceSpark Streaming如何保证exactly once扩展:Storm\Spark Streaming\Flink的消费语义 Kafka自身的精准一次性 ack at least once+幂等性 = exactly once kafka事务 SparkStreaming exa

u010737756的博客 2193
上一篇: Kafka之精确一次处理语义
下一篇: Kafka Consumer如何实现精确一次消费数据
王树民
博客等级 码龄10年 912粉丝 560原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值