Kafka offset管理
参考文章:Kafka offset管理
kafka系列之(3)——Coordinator与offset管理和Consumer Rebalance
Kafka中的每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序号,用于partition唯一标识一条消息。
Offset记录着下一条将要发送给Consumer的消息的序号。
Offset从语义上来看拥有两种:Current Offset和Committed Offset。
1. Current Offset
Current Offset保存在Consumer客户端中,它表示Consumer希望收到的下一条消息的序号。它仅仅在poll()方法中使用。例如,Consumer第一次调用poll()方法后收到了20条消息,那么Current Offset就被设置为20。这样Consumer下一次调用poll()方法时,Kafka就知道应该从序号为21的消息开始读取。这样就能够保证每次Consumer poll消息时,都能够收到不重复的消息。
2. Committed Offset
Committed Offset保存在Broker上,它表示Consumer已经确认消费过的消息的序号。主要通过
commitSync和commitAsync
API来操作。举个例子,Consumer通过poll() 方法收到20条消息后,此时Current Offset就是20,经过一系列的逻辑处理后,并没有调用consumer.commitAsync()或consumer.commitSync()来提交Committed Offset,那么此时Committed Offset依旧是0。Committed Offset主要用于Consumer Rebalance。在Consumer Rebalance的过程中,一个partition被分配给了一个Consumer,那么这个Consumer该从什么位置开始消费消息呢?答案就是Committed Offset。另外,如果一个Consumer消费了5条消息(poll并且成功commitSync)之后宕机了,重新启动之后它仍然能够从第6条消息开始消费,因为Committed Offset已经被Kafka记录为5。
总结,Current Offset是针对Consumer的poll过程的,它可以保证每次poll都返回不重复的消息;而Committed Offset是用于Consumer Rebalance过程的,它能够保证新的Consumer能够从正确的位置开始消费一个partition,从而避免重复消费。
在Kafka 0.9前,Committed Offset信息保存在zookeeper的[consumers/{group}/offsets/{topic}/{partition}]目录中(zookeeper其实并不适合进行大批量的读写操作,尤其是写操作)。而在0.9之后,所有的offset信息都保存在了Broker上的一个名为__consumer_offsets的topic中。
Kafka集群中offset的管理都是由Group Coordinator中的Offset Manager完成的。
3. Group Coordinator
Group Coordinator是运行在Kafka集群中每一个Broker内的一个进程。主要负责Consumer Group的管理,Offset位移管理以及Consumer Rebalance。
对于每一个Consumer Group,Group Coordinator都会存储以下信息:
- 订阅的topics列表
- Consumer Group配置信息,包括session timeout等
- 组中每个Consumer的元数据。包括主机名,consumer id
- 每个Group正在消费的topic partition的当前offsets
- Partition的ownership元数据,包括consumer消费的partitions映射关系
Consumer Group如何确定自己的coordinator是谁呢? 简单来说分为两步:
1> 确定Consumer Group offset信息将要写入__consumers_offsets topic的哪个分区。
具体计算公式:
__consumers_offsets partition# = Math.abs(groupId.hashCode()
% offsets.topic.num.partitions) //offsets.topic.num.partitions默认值为50。
2> 该分区leader所在的broker就是被选定的coordinator
4. Offset存储模型
由于一个partition只能固定的交给一个消费者组中的一个消费者消费,因此Kafka保存offset时并不直接为每个消费者保存,而是以groupid-topic-partition -> offset的方式保存。如图所示:
Kafka在保存Offset的时候,实际上是将Consumer Group和partition对应的offset以消息的方式保存在__consumers_offsets这个topic中。
__consumers_offsets默认拥有50个partition,可以通过
Math.abs(groupId.hashCode() % offsets.topic.num.partitions)
的方式来查询某个Consumer Group的offset信息保存在__consumers_offsets的哪个partition中。
下图展示了__consumers_offsets中保存的offset消息的格式:
如图所示,一条offset消息的格式为groupid-topic-partition -> offset。因此consumer poll消息时,已知groupid和topic,又通过Coordinator分配partition的方式获得了对应的partition,自然能够通过Coordinator查找__consumers_offsets的方式获得最新的offset了。
5. Offset查询
前面我们已经描述过offset的存储模型,它是按照groupid-topic-partition -> offset的方式存储的。然而Kafka只提供了根据offset读取消息的模型,并不支持根据key读取消息的方式。那么Kafka是如何支持Offset的查询呢?
答案就是Offsets Cache!!
如图所示,Consumer提交offset时,Kafka Offset Manager会首先追加一条条新的commit消息到__consumers_offsets topic中,然后更新对应的缓存。读取offset时从缓存中读取,而不是直接读取__consumers_offsets这个topic。
6. Log Compaction
我们已经知道,Kafka使用groupid-topic-partition -> offset*的消息格式,将Offset信息存储在__consumers_offsets topic中。请看下面一个例子:
如图,对于audit-consumer这个Consumer Group来说,上面的存储了两条具有相同key的记录:PageViewEvent-0 -> 240和PageViewEvent-0 -> 323。事实上,这就是一种无用的冗余。因为对于一个partition来说,我们实际上只需要它当前最新的Offsets。因此这条旧的PageViewEvent-0 -> 240记录事实上是无用的。
为了消除这样的过期数据,Kafka为__consumers_offsets topic设置了Log Compaction功能。Log Compaction意味着对于有相同key的的不同value值,只保留最后一个版本。如果应用只关心key对应的最新value值,可以开启Kafka的Log Compaction功能,Kafka会定期将相同key的消息进行合并,只保留最新的value值。
这张图片生动的阐述了Log Compaction的过程:
下图阐释了__consumers_offsets topic中的数据在Log Compaction下的变化:
在新建topic时添加
log.cleanup.policy=compact参数就可以为topic开启Log Compaction功能。
7. auto.offset.reset参数
auto.offset.reset表示如果Kafka中没有存储对应的offset信息的话(有可能offset信息被删除),消费者从何处开始消费消息。它拥有三个可选值:
- earliest:从最早的offset开始消费
- latest:从最后的offset开始消费
- none:直接抛出exception给consumer
看一下下面两个场景:
Consumer消费了5条消息后宕机了,重启之后它读取到对应的partition的Committed Offset为5,因此会直接从第6条消息开始读取。此时完全依赖于Committed Offset机制,和
auto.offset.reset配置完全无关。新建了一个新的Group,并添加了一个Consumer,它订阅了一个已经存在的Topic。此时Kafka中还没有这个Consumer相应的Offset信息,因此此时Kafka就会根据
auto.offset.reset配置来决定这个Consumer从何处开始消费消息。
智能推荐
聊聊 Kafka+Spark Streaming 管理offset的两种方法
Kafka配合Spark Streaming是大数据领域常见的黄金搭档之一,主要是用于数据实时入库或分析。 为了应对可能出现的引起Streaming程序崩溃的异常情况,我们一般都需要手动管理好Kafka的offset,而不是让它自动提交,即需要将 enable.auto.commit 设为false。只有管理好offset,才能使整个流式系统最大限度地接近exactly once语义。 管理off...
【Kafka】Kafka使用代码设置offset值
1.概述 转载:https://www.cnblogs.com/jinniezheng/p/6379639.html wiki地址https://cwiki.apache.org/confluence/display/KAFKA/Committing+and+fetching+consumer+offsets+in+Kafka Kafka监控——获取Partition的Lo...
kafka存储机制以及offset
1.前言 一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一。 下面将从Kafka文件存储机制和物理结构角度,分析Kafka是如何实现高效文件存储,及实际应用效果。 2.Kafka文件存储机制 Kafka部分名词解释如下: Broker:消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。 Topic:...
Kafka - 指定offset进行消费
Kafka - 指定offset进行消费 在网上搜索之后发现了,从消息队列最开始的位置对数据进行消费,主要代码如下: 轮询20次,查看数据的消费结果: 从控制台的输出情况可以看到,kafka的消费者已经从头对数据进行了消费。同时也会发现,在拉取数据的时候会有很多次一条数据也没有拉下来,所以如果不是使用的死循环,本例中的20次轮询也可能会一条数据也消费不到。 在阅读他人博文的时候发现了有seekTo...
kafka的offset相关知识
文章目录 1、Offset存储模型 2、Offset查询 3、Offset管理方式 1、Offset存储模型 由于一个partition只能固定的交给一个消费者组中的一个消费者消费,因此Kafka保存offset时并不直接为每个消费者保存,而是以 groupid-topic-partition -> offset 的方式保存。 如图所示: Kafka在保存Offset的时候,实际上是将Con...
猜你喜欢
冒泡排序,及改进方式,性能优化400%>>>附图解加源码
首先源码附上,源码中带有注释,看不懂没关系,源码后面附带图解,最后附上代码效率提升图 源码如下: 方案一:其实实现很简单,两层循环,每次内层迭代出最大的一个值,将其放入数组最后一个位置,外层循环的末端便往前移一位。其原理如下图 方案一代码块: 方案二:优化改进 仔细观察上面的图,我们不难发现当迭代到图下这样的情况时,其实已经全排序好了,但是我们还是需要对它进行1,2,3,4,5,6的迭代,这些情况...
css3常用选择器
先介绍一下基本选择器,如下几种 *:通配符。选择页面的所有元素 E:元素选择器。对页面的一些元素进行选择,如p,div,li等 .class:类选择器 #id:id选择器。一个Id在一个页面中只能选择,这是和类选择器的区别 E F:后代选择器。如ul li。选中ul下的li E>F:子元素选择器。如下,可以用 h1 > strong {color:red;}使h1的子元素strong变...
python is not set from command line or npm configuration
问题 猜测原因 python版本冲突 解决方案 去官网找到最新版本python 点击下载,注意记住你下载的目录,下载好以后,打开这个目录下的文件夹,Python310, 整个文件夹复制一下 在项目里运行npm config list --json 找到python的路径 我的是 C:\\Python27\\python.exe 说明项目里用的还是py...
Java8 Stream流操作
前言 我们常常需要将一个容器转化成另一个容器,或是对这个容器中的数据进行批量处理,这时使用Stream流可以大大减少我们的工作量。 1 Stream概述 Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。 那么什么是Stream? Stream将要处理的元素集合看作一种流,在流的过程中,借助St...
带你玩转Visual Studio——带你跳出坑爹的Runtime Library坑
在Windows下进行C++的开发,不可避免的要与Windows的底层库进行交互,然而VS下的一项设置MT、MTd、MD和MDd却经常让人搞迷糊,相信不少人都被他坑过,特别是你工程使用了很多第三库的时候,及容易出现各种链接问题。看一下下面这个错误提示: LIBCMT.lib(_file.obj) : error LNK2005: ___initstdio already defined...
