Kafka消息偏移量的演变
一、Kafka 0.7.x
1、非压缩消息
MessageSet 格式的时候就说Offset字段存储的是消息存储到磁盘之后的物理偏移量
从上图可以看出,每条消息存在磁盘的偏移量是其距离文件开头的绝对偏移量。比如上面第一条消息的偏移量是0;第二条消息的偏移量是第一条消息的总长度;第三条消息是其前两条消息总长度;以此类推。这种方式存储消息的偏移量很好理解,处理起来也很方便。
消息存储到磁盘的偏移量是由 Broker 处理完成的,原因很简单,因为只有 Broker 端才知道现在 Log 的最新偏移量; Producer 端是无法获取的。这个逻辑同样适用于 Kafka 0.8.x 、Kafka 0.9.x 以及 Kafka 0.10.x。
2、压缩消息
压缩消息内部的子消息并不设置偏移量,外部的消息偏移量设置规则和非压缩消息逻辑一致。
3、优缺点
缺点:
很难对压缩消息内部的消息进行checkpoint;
很难对压缩消息内部的消息进行定位操作;
log compaction 不好做。
优点:
Broker 处理来自 Producer 的消息速度非常快
CPU 的利用率一般 < 10%
一般网络是这里的主要瓶颈。
二、Kafka 0.8.x
1、非压缩消息
上图很明显的一个变化就是偏移量的指已经不是消息的物理偏移量了,而是一个绝对偏移量,这个偏移量从0开始。第一条消息的绝对偏移量是0;第二条消息的绝对偏移量是1;依次类推。同样,这个偏移量的计算也是由 Broker 处理的。
2、压缩消息
压缩消息内部的消息也有偏移量了!对于压缩消息的偏移量处理相对于 Kafka 0.7.x 复杂多了。
Producer端对于压缩消息偏移量处理
Producer 端会对压缩消息中内部的消息设置一个相对偏移量。从0开始,依次到n-1,这里的n代表压缩消息的条数。
偏移量设置好之后,Producer 端会将整个 MessageSet 进行压缩,然后发送到Broker。
Broker端对于压缩消息偏移量处理
Broker 端接收到 Producer 发送过来的压缩消息,忽略掉 Producer 端对压缩消息偏移量的而处理,其会先解压接收到的压缩消息,然后根据 nextOffset 依次设置压缩消息内部消息的偏移量,最后整个压缩消息的偏移量为最后一条内部消息的绝对偏移量。举个例子,比如图中最后一条消息的偏移量是7,那么 nextOffset 应该为 8;现在 Broker 接收到新消息,
偏移量设置完之后, Broker 需要重新压缩刚刚解压好的消息,最后会将这条消息追加到 Log 文件中。
Client端对于压缩消息偏移量处理
Client 端如果请求压缩的消息,Broker 端会直接将整个压缩的消息发送到 Client,Client会自动将压缩的消息解压,解压的过程对我们编程的人来说是无感知的。
为什么整个压缩消息的偏移量为最后一条内部消息的绝对偏移量呢?
由于 FetchRequest 协议中的 offset 是要求 Broker 提供大于等于这个 offset 的消息,因此 Broker 会检查log,找到符合条件的,然后传输出去。那么由于FetchRequest中的offset位置的消息可位于一个compressed message中,所以broker需要确定一个compressed Message是否需要被包含在respone中。
(1)如果我们将整个压缩消息的偏移量为第一条内部消息的绝对偏移量。那么,我们对于这个Message是否应包含在response中,无法给出是或否的回答。比如 FetchRequest 中指明的开始读取的offset是14,而一个compressed Message的offset是13,那么这个Message中可能包含offset为14的消息,也可能不包含。
(2)如果我们将整个压缩消息的偏移量为最后一条内部消息的绝对偏移量。那么,可以根据这个offset确定这个Message应不应该包含在response中。比如 FetchRequest 中指明的开始读取的offset是14,那么如果一个compressed Message的offset是13,那它就不该被包含在response中。而当我们顺序排除这种不符合条件的Message,就可以找到第一个应该被包含在response中的Message(压缩或者未压缩), 从它开始读取。
在第一种情况下(最小offset),我们尽管可以通过连续的两个Message确定第一个Message的offset范围,但是这样在读取时需要在读取第二个Message的offset之后跳回到第一个Message, 这通常会使得最近一次读(也就读第二个offset)的文件系统的缓存失效。而且逻辑比第二种情况更复杂。在第二种情况下,broker只需要找到第一个其offset大于或等于目标offset的Message,从它可以读取即可,而且也通常能利用到文件系统缓存,因为offset和消息内容有可能在同一个缓存块中。
3、优缺点
这个版本的压缩消息中内部的消息也有偏移量了,这样就可以对内部消息进行定位处理。而且log compaction实现起来很方便。但是这个版本的消息偏移量也有个很明显的问题,就是对于每条压缩的消息,Broker 端都需要对其进行解压,设置好相关的偏移量之后,再进行压缩,这些都会占用很多的CPU资源。
三、Kafka 0.10.x
Kafka 0.10.x 对于非压缩的消息偏移量处理和 Kafka 0.8.x 一致,这里就不再介绍了。这里主要介绍 Kafka 0.10.x 对压缩消息偏移量处理逻辑。和 Kafka 0.8.x 处理内部消息偏移量逻辑不一样,这个版本对于内部消息偏移量使用的是相对偏移量,从0开始,依次到n-1,这里的n代表压缩消息的条数。所以 Kafka 0.10.x 压缩消息处理完偏移量之后看起来像下面的结果:
上图可以看出,相对于 Kafka 0.8.x 仅仅是内部消息偏移量变成了相对偏移量,整个压缩消息的偏移量处理逻辑和 Kafka 0.8.x 一致。下面我们将详细介绍 Kafka 是如何处理的:
Producer端对于压缩消息偏移量处理
这个逻辑和 Kafka 0.8.x 处理逻辑一致,不再介绍。有一点需要注意,Kafka 0.10.x 会将消息的 magic 值设置为 1,用于区分其他版本的消息,后面会介绍这样设置的用处。
Broker端对于压缩消息偏移量处理
Broker 端接收到 Producer 发送过来的压缩消息,其也是先解压接收到的压缩消息,然后做一堆的判断,比如 消息的 magic 值是否大于0,压缩消息内部的消息偏移量值是否连续(0,1,2,3这样的)等,如果符合这些条件(inPlaceAssignment = true
),那么 Broker 会直接处理整个压缩消息外部的偏移量,内部消息的偏移量不需要设置,因为这个在 Producer 端已经设置好了;并不需要再次压缩消息,最后会将这条消息追加到 Log 文件中。
如果 inPlaceAssignment = false
,这时候会直接操作解压后的消息,并给压缩消息内部消息设置偏移量,最后设置整个压缩消息的偏移量;这时候会忽略掉 Producer 端为压缩消息设置的偏移量,包括内部消息和整个压缩消息的偏移量。整个处理逻辑分为两种情况:
(1)如果接收到的消息不是由 Kafka 0.10.x 版本Producer客户端发送过来的,那么消息的 magic 值会等于0,这时候 Broker 设置偏移量逻辑和 Kafka 0.8.x 处理逻辑一致,也就是不管内部消息还是整个压缩消息的偏移量都是使用绝对偏移量;
(2)如果接收到的消息是由 Kafka 0.10.x 版本Producer客户端发送过来的,那么消息的 magic 值会等于1,这时候 Broker 会将压缩消息内部的消息偏移量设置成相对的,从0开始,依次到 n-1 ,最后整个压缩消息的偏移量为 nextOffset + n - 1
,其中n为压缩消息的条数。处理结果如下:
偏移量设置完之后,对于inPlaceAssignment = false
,不管是由什么版本发送过来的消息, Broker 需要重新压缩刚刚解压好的消息,最后会将这条消息追加到 Log 文件中。
Client端对于压缩消息偏移量处理
对不同版本的 Client 请求, Broker 会做出不同的判断:对于非 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送不会使用零拷贝技术;而如果是 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送才会使用零拷贝技术
Kafka消息偏移量的演变相关推荐
- 一文看懂Kafka消息格式的演变
欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...
- Apache Kafka消息格式的演变(0.7.x~0.10.x)
用 Kafka 这么久,从来都没去了解 Kafka 消息的格式.今天特意去网上搜索了以下,发现这方面的资料真少,很多资料都是官方文档的翻译:而且 Kafka 消息支持压缩,对于压缩消息的格式的介绍更少 ...
- kafka 消息格式设计实现
目前kafka消息格式有三个版本(假定v0,v1,v2),0.10.0之前使用的是v0版本,之后慢慢演变出v1,v2,后两个版本在设计方式上没有什么特别大的区别,只是做了些空间上的优化,同样的消息,新 ...
- kudu接受kafka消息_Kafka入门详解
1.1 什么是kafka? Kafka最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的 ...
- go 实现 kafka 消息发送、接收
引言 网络上关于 go 实现 kafka 消息发送和接收的文章很多,但是实际操作起来又不是很清楚,本文在网络资源的基础上,结合自己搭建过程中遇到的问题进行了总结. 本文的实验主机:Mac笔记本. 一. ...
- kafka消息的分发与消费(一)
关于 Topic 和 Partition: Topic: 在 kafka 中,topic 是一个存储消息的逻辑概念,可以认为是一个消息集合.每条消息发送到 kafka 集群的消息都有一个类别.物理上来 ...
- Kafka整体结构图、Consumer与topic关系、Kafka消息分发、Consumer的负载均衡、Kafka文件存储机制、Kafka partition segment等(来自学习资料)
##1. Kafka整体结构图 Kafka名词解释和工作方式 Producer : 消息生产者,就是向kafka broker发消息的客户端. Consumer : 消息消费者,向kafka ...
- 带你认识三种kafka消息发送模式
摘要:在kafka-0.8.2之后,producer不再区分同步(sync)和异步方式(async),所有的请求以异步方式发送,这样提升了客户端效率. 本文分享自华为云社区<kafka消息发送模 ...
- kafka消息队列的概念理解
kafka在大数据.分布式架构中都很流行.kafka可以进行流式计算,也可以做为日志系统,还可以用于消息队列. kafka作为消息队列的优点: 分布式的系统 高吞吐量.即使存储了许多TB的消息,它也保 ...
最新文章
- jquery实现返回顶部按钮和scroll滚动功能[带动画效果] 转载
- 深入理解 JavaScript 原型
- 如何在awk中引用外部变量
- CISC-235 Fall 2018 Assignment
- Hbase hbck2下载编译和基本使用
- 使用javaMail收邮件 支持附件下载
- vue2.0框架认识
- OkHttp源码深度解析
- QStyleOptionGraphicsItem实现自绘按钮悬浮按下状态
- Java ArrayList与LinkedList数据结构和特点
- s7-1200跟mysql_让西门子S7-1200直接连接MySQL数据库!!!
- ImportError: No module named urllib2
- 有没有妈妈生了孩子一点不像自己的,觉得亏吗?
- java jython_将对象从Java传递到Jython时保留Java类型
- 医院设备管理系统方案/案列/软件/APP/小程序/网站
- java 贝叶斯抠图_毕业论文 基于贝叶斯算法的自动抠图程序设计与实现.doc
- Stacer ---- Linux系统优化和监测工具
- STM32f4日记9之LD3320语音识别(您的私人语音助手MICRO)
- 电脑上传,如何查看电脑上传速度
- 数据库系统概论----设计ER图
热门文章
- 高性能分布式游戏服务器框架
- 主板各种插针接口与机箱(电源)的接法
- 最新vx红包封面小程序源码 附教程
- 电商系统之延长收货与申请退款
- Windows丢失缺少api-ms-win-crt-process-l1-1-0.dll解决方法
- 小标题 html,论文的小标题格式
- 【Java】算法积累1——大整数相加
- [论文笔记] Detection of Glottal Closure Instants from Speech Signals: CNN Method
- 互联网创业公司如何防御DDoS攻击?
- fastqc检验时不能执行java_安装Fastqc软件遇到的坑