kafka的offset理解

kafka的offset理解

kafka是顺序读写,具备很好的吞吐量。实现原理是
每次生产消息时,都是往对应partition的文件中追加写入,而消息的被读取状态是由consumer来维护的
所以每个partition中offset一般都是连续递增的(如果开启了压缩,因为对旧数据的merge会导致不连续)
被读取的消息并不会删除,所以每次都是追加写入顺序读写,具备很好的吞吐量。
这也是为什么说kafka的broker是无状态的,整个过程中伴随由zookeeper的协调参与,一般是不同broker存储了不同partition或副本数据,当存在多个副本时,从那个broker读取数据时由zookeeper决定的,一般会由一台kafka作为leader(被读取),如果该kafka不可用时,zookeeper切换到别的broker,因为broker在zookeeper上维护一个 /broker/ids/{id}的临时节点,如果kafka不可用,该节点也会被删除,kafka集群会根据该节点的信息,切换被读取的kafka
实现过程是 consumer在消费消息后,向broker中有个专门维护每个consumer的offset的topic生产一条消息,记录自己当前已读的消息的offset+1的值作为新的offset的消息。当然在旧版本的实现是在zookeeper上有个节点存放这个offset,当时后面考虑性能问题,kafka改到了topic里,同时可以自由配置使用zookeeper还是使用topic,以下是刚刚各个情况在zookeeper上的展示
zookeeper
而在kafka存放topic数据的目录中,存有一个我们创建的test主题的目类(因为没有别的分区,所以是分区0),以及存放__consumer_offsets的50个分区目录
在这里插入图片描述
每次consumer消费消息时,kafka都会根据该topic下对于该consumer记录的offset,传递对应消息,当offset不存在时,根据auto.offset.reset配置的值,会有几种不同策略

earliest
无指定的offset时,从头开始消费

latest
无提交的offset时,消费该分区下最新产生的消息

none
topic不存在指定的offset,则抛出异常

zero copy

kafka之所以使用了文件存储还可以有这么高的吞吐量得益于他利用了操作系统的零拷贝技术,主要是利用Channel的transferTo方法
普通IO模式下(read,write),实际经过四次的文件内容复制

1、将磁盘文件数据,copy到操作系统内核缓冲区;
2、将内核缓冲区的数据,copy到应用程序的buffer;
3、将应用程序buffer中的数据,copy到socket发送缓冲区(属于操作系统内核);
4、将socket buffer的数据,copy到网卡,由网卡进行网络传输。

而在零拷贝技术下,只有两步

1.将磁盘文件数据读取到操作系统内核缓冲区
2.将内核缓冲区数据copy到网卡,由网卡进行网络传输

欢迎找歪歪梯聊骚