提交和偏移量

每次调用poll 方法,总是返回生产者写入Kafka但还没有被消费者读取过的记录我们因此可以追踪到哪些记录时被群组里的哪个消费者读取过的。

我们把更新分区当前位置的操作叫做提交。

那么消费者时如何提交偏移量的呢?消费者往一个叫做_consumer_offset的特殊主题发送消息,消息里包含每个分区的偏移量。如果消费者一直处于运行状态,那么偏移量没有什么用处。不过如果消费者发生崩溃或者有新的消费者加入群组,就会触发在均衡,完成再均衡之后,每个消费者可能分配到新的分区,而不是之前那一个,为了能够继续之前的工作,消费者需要读取每个分区最后一次提交的偏移量,然后从偏移量指定的地方继续处理。

如果提交的偏移量小于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息就会被重复处理。

如果提交的偏移量大于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息将会丢失。

KafkaConsumer API提供了很多方式来提交偏移量。

自动提交

最简单的方式时让消费者自己提交偏移量,如果enable.auto.commit被设为true,那么每过5s,消费者自动把从poll方法接收到的最大偏移量提交上去。提交间隔时间由auto.commit.interval.ms控制,默认值时5s,如果这个5s内发生了再均衡,那么就会有消息被重复处理。自动提交虽然方便,但是并没有为开发者留有余地来避免重复处理消息。

手动提交

开发者可以在必要的时候提交当前偏移量,而不是基于时间间隔。把enable.auto.commit设为false,让应用程序决定何时提交偏移量。使用commitSync方法提交偏移量最简单也最可靠。这个API会提交由poll方法返回的最新偏移量,提交成功后马上返回,如果提交失败就会抛出异常。

commitSync方法将会提交由poll方法返回的最新偏移量,所以处理完所有记录后要确保调用了commitSync,否则还是会有丢失消息的风险。如果发生了再均衡,从最近一批消息到发生在均衡之间的所有消息都将会被重复处理。

异步提交

手动提交有一个不足之处,在broker对提交请求作出回应之前,应用程序会一直阻塞,这会影响应用程序的吞吐量,我们可以通过降低提交频率来提升吞吐量,但如果发生了再均衡,会增加重复消息的数量。

这个时候可以考虑使用异步提交API,我们只管发送提交请求,无需等待broker的响应。

在成功提交或碰到无法恢复的错误之前,commitSync方法会一直重试,但是commitAsync不会,他之所以不进行重试,是因为它在收到服务器响应的时候,可能有一个更大的偏移量已经提交成功。

我们之所以提到这个问题的复杂性和提交顺序的重要性,是因为commitAsync方法支持回调,在broker作出响应时会执行回调。回调经常被用于记录提交错误或者生成度量指标,不过如果用于重试,一定注意提交的顺序。

我们可以使用一个单调递增的序列号来维护异步提交的顺序,在每次提交偏移量之后或在回调里提交偏移量时递增序列号。在进行重试前,先检查回调的序列号和即将提交的偏移量是否相等,如果相等,说明没有新的提交,那么可以安全地进行重试,如果序列号比较大,说明有一个新的提交意见发送,应该停止重试。

提交特定的偏移量

提交偏移量的频率和处理消息的频率时一样的,但如果向频繁提交怎么办?

消费者API允许在调用commitSync和commitAsync方法时传进去希望提交的分区和偏移量map。

再均衡监听器

在为消费者分配新分区或者移除旧分区时,可以通过消费者API执行一些应用程序代码,在调用subscribe方法时传进去一个ConsumerRebalanceListener实例就可以了,它有两个需要实现的方法:

onPartitionRevoked方法会在再均衡开始之前和消费者停止读取消息之后被调用。如果在这里提交偏移量,下一个接管分区的消费者就知道该从哪里开始读取。

onPartitionAssigned方法会在重新分配分区之后和消费者开始读取消息之前被调用。

从特定偏移量开始处理记录

有时候需要从特定的偏移量开始读取消息。如果想从分区的起始位置开始读取消息,或者直接跳到分区的末尾开始读取消息,可以使用seekToBeginning方法和seekToEnd方法。

如果保存记录和偏移量可以在一个原子操作里完成,就可以避免重复处理。如果在同一个事务里把记录和偏移量都写到数据库里,那么我们就会知道记录和偏移量要么都成功,要么都失败,然后重新处理记录。

现在的问题时:如果偏移量时保存在数据库里而不是Kafka里,那么消费者在得到新分区时怎么知道该从哪里开始读取?这个时候可以使用seek方法,在消费者启动或分配到新分区时,可以使用seek方法查找保存到数据库里的偏移量。如何退出

如果确定要退出循环,需要通过另外一个线程调用consumer.wakeup方法。

kafka笔记4(2)的更多相关文章

  1. Kafka笔记整理(三):消费形式验证与性能测试

    Kafka消费形式验证 前面的<Kafka笔记整理(一)>中有提到消费者的消费形式,说明如下: .每个consumer属于一个consumer group,可以指定组id.group.id ...

  2. Kafka笔记整理(一)

    Kafka简介 消息队列(Message Queue) 消息 Message 网络中的两台计算机或者两个通讯设备之间传递的数据.例如说:文本.音乐.视频等内容. 队列 Queue 一种特殊的线性表(数 ...

  3. Kafka笔记—可靠性、幂等性和事务

    这几天很忙,但是我现在给我的要求是一周至少要出一篇文章,所以先拿这篇笔记来做开胃菜,源码分析估计明后两天应该能写一篇.给自己加油~,即使没什么人看. 可靠性 如何保证消息不丢失 Kafka只对&quo ...

  4. Kafka笔记

    最近做的一个项目需要跟Kafka打交道,学习了很多相关知识,就到这里来汇总一下. kafka是一个传递消息的系统,原本是用来快速记录海量log的,现在也经常用作消息队列.它主要由三个部分组成,prod ...

  5. kafka笔记-Kafka在zookeeper中的存储结构【转】

    参考链接:apache kafka系列之在zookeeper中存储结构  http://blog.csdn.net/lizhitao/article/details/23744675 1.topic注 ...

  6. Kafka笔记--指定消息的partition规则

    参数的设定:参考资料 不错的资料:http://blog.csdn.net/honglei915/article/details/37697655 http://developer.51cto.com ...

  7. Kafka笔记--监控系统KafkaOffsetMonitor

    KafkaOffsetMonitor下载链接: http://download.csdn.net/detail/changong28/7930337github官方:https://github.co ...

  8. Kafka笔记--使用ubuntu为bocker(服务器)windows做producer和comsumer(客户端)

    原文连接:http://www.cnblogs.com/davidwang456/p/4201875.html 程序仍然使用之前的一篇博文中的例子 :http://www.cnblogs.com/gn ...

  9. Kafka笔记--参数说明及Demo

    参考资料:http://blog.csdn.net/honglei915/article/details/37563647参数说明:http://ju.outofmemory.cn/entry/119 ...

  10. Kafka笔记--分布式环境搭建

    部署: http://www.cnblogs.com/likehua/p/3999538.html http://blog.csdn.net/kimmking/article/details/8263 ...

随机推荐

  1. jquery大事-resize()办法

    为了形成用于电流大小的缩放对象构造监控事件. JQuery提供resize大事.在每一个匹配元素的resize函数到事件绑定,让我们适应窗口大小.对齐等.,档窗体改变大小时触发 这里有两种监听方式,一 ...

  2. Linux 网络编程——TCP

    环境:Linux  C   一.协议介绍      TCP是面向连接的协议,提供可靠的数据传输:TCP协议的可靠传输基于三次握手.四次挥手以及确认重传机制实现.下面来具体展示下TCP的三次握手.四次挥 ...

  3. 使用Apache Tiles3.x构建界面布局

    Tiles是一个免费的开源模板Java应用程序的框架.基于复合模式简化的用户界面的构建.对于复杂的网站仍是最简单.最优雅的方式与任何MVC技术一起工作.Struts2对Tiles提供了支持,如今Til ...

  4. 《Java并发编程实战》第十二章 测试并发程序 读书笔记

    并发测试分为两类:安全性测试(无论错误的行为不会发生)而活性测试(会发生). 安全測试 - 通常採用測试不变性条件的形式,即推断某个类的行为是否与其它规范保持一致. 活跃性測试 - 包含进展測试和无进 ...

  5. Scala-Numbers

    Scala之Numbers 一.前言 前面已经学习了Scala中的String,接着学习Scala的Numbers. 二.Numbers 在Scala中,所有的数字类型,如Byte,Char,Doub ...

  6. 窗体的基类中没有设定大小,所以才不能居中,若要窗体居中,必须使用setfixedsize()函数或者resize()函数设定窗体的大小,居中才能正常使用

    最近开发中,遇到了窗体不能居中的问题,看了网上的很多文章,窗口居中,无非都是move至窗口的中心目标; 有两种方式, 一种在构造函数中直接计算中心坐标; 另一种是在窗口show后再move至相应坐标. ...

  7. python3批量查询域名是否注册

    #!/usr/local/bin/python3 #coding=utf-8 import re,sys,os,random,time, base64 import urllib.parse, url ...

  8. EBS OAF 发展 URL商标、加密和编码

    EBS OAF 发展 URL商标.加密和编码 (版权声明.我原来的或翻译的文章,如需转载,转载的个人学习,转载请注明出处:否则,请与我联系.版权所有) 马克 当您指定页面定义声明URL参数,文本也能够 ...

  9. 用C++写UI库最本质的思想就是不用C++写UI(如何用 C++ 从零编写 GUI?内含多个开源UI作者的回复,非常精彩)

    作者:Bingo链接:https://www.zhihu.com/question/24462113/answer/83371803来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  10. RestSharp 封状实例

    1 public class Rest<T> { private static Logger logger = LogManager.GetCurrentClassLogger(); pr ...