热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:图解ApacheKafka消息偏移量的演变(0.7.x~0.10.x)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了图解ApacheKafka消息偏移量的演变(0.7.x~0.10.x)相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)相关的知识,希望对你有一定的参考价值。


如下面图片不清晰,请访问https://www.iteblog.com/archives/2235.html,或点击下面阅读原文进行阅读。

我在《文章中介绍了 Kafka 几个版本的消息格式。仔细的同学肯定看到了在 MessageSet 中的 Message 都有一个 Offset 与之一一对应,本文将探讨 Kafka 各个版本对消息中偏移量的处理。同样是从 Kafka 0.7.x 开始介绍,并依次介绍到 Kafka 0.10.x,由于 Kafka 0.11.x 正在开发中,而且消息格式已经和之前版本大不一样,所以这里不打算介绍。






Kafka 0.7.x




我在《文章中介绍 MessageSet 格式的时候就说Offset字段存储的是消息存储到磁盘之后的物理偏移量;注意,这里是物理偏移量,什么意思呢?看下面的图大家应该就会明白:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图一

从上图可以看出,每条消息存在磁盘的偏移量是其距离文件开头的绝对偏移量。比如上面第一条消息的偏移量是0;第二条消息的偏移量是第一条消息的总长度;第三条消息是其前两条消息总长度;以此类推。这种方式存储消息的偏移量很好理解,处理起来也很方便。

大家需要注意,消息存储到磁盘的偏移量是由 Broker 处理完成的,原因很简单,因为只有 Broker 端才知道现在 Log 的最新偏移量; Producer 端是无法获取的。这个逻辑同样适用于 Kafka 0.8.x 、Kafka 0.9.x 以及 Kafka 0.10.x。

上面仅仅是非压缩消息的偏移量处理,我们来看看这个版本压缩消息的偏移量处理是咋样的,如下图所示:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图二

正如上图所示,压缩消息内部的子消息并不设置偏移量,外部的消息偏移量设置规则和非压缩消息逻辑一致。


优缺点

这种设计存在几个问题:



  1. 很难对压缩消息内部的消息进行checkpoint;


  2. 很难对压缩消息内部的消息进行定位操作;


  3. log compaction 不好做。


但是这样的设计也有好处:



  1. Broker 处理来自 Producer 的消息速度非常快


  2. CPU 的利用率一般 <10%


  3. 一般网络是这里的主要瓶颈。






Kafka 0.8.x




针对 Kafka 0.7.x 版本消息偏移量存在的多种问题,这个版本对其进行了解决,这个版本消息偏移量处理结果如下:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图三

我们先不管这个消息格式到底有何变化(真想知道的话,请参见《Apache Kafka消息格式的演变(0.7.x~0.10.x)》),上图很明显的一个变化就是偏移量的指已经不是消息的物理偏移量了,而是一个绝对偏移量,这个偏移量从0开始。第一条消息的绝对偏移量是0;第二条消息的绝对偏移量是1;依次类推。同样,这个偏移量的计算也是由 Broker 处理的。

压缩消息偏移量的处理逻辑就比这个复杂多了,先来看看一张结果图吧:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图四

这个图相对于 Kafka 0.7.x压缩消息的最明显变化就是,压缩消息内部的消息也有偏移量了!对于压缩消息的偏移量处理相对于 Kafka 0.7.x 复杂多了,下面我们将详细介绍 Kafka 是如何处理的:


Producer端对于压缩消息偏移量处理

Producer 端会对压缩消息中内部的消息设置一个相对偏移量。从0开始,依次到n-1,这里的n代表压缩消息的条数。处理的效果如下:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图五

偏移量设置好之后,Producer 端会将整个 MessageSet 进行压缩,然后发送到Broker。


Broker端对于压缩消息偏移量处理

Broker 端接收到 Producer 发送过来的压缩消息,忽略掉 Producer 端对压缩消息偏移量的而处理,其会先解压接收到的压缩消息,然后根据 nextOffset 依次设置压缩消息内部消息的偏移量,最后整个压缩消息的偏移量为最后一条内部消息的绝对偏移量。举个例子,比如图四最后一条消息的偏移量是7,那么 nextOffset 应该为 8;现在 Broker 接收到图五的消息,最后的处理如下:

图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)

图六

偏移量设置完之后, 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和消息内容有可能在同一个缓存块中。


优缺点

这个版本的压缩消息中内部的消息也有偏移量了,这样就可以对内部消息进行定位处理。而且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 压缩消息处理完偏移量之后看起来像下面的结果:

图解Apache Kafka消息偏移量的演变(0.7.x~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为压缩消息的条数。处理结果如下:


图解Apache Kafka消息偏移量的演变(0.7.x~0.10.x)
图八

偏移量设置完之后,对于inPlaceAssignment = false,不管是由什么版本发送过来的消息, Broker 需要重新压缩刚刚解压好的消息,最后会将这条消息追加到 Log 文件中。


Client端对于压缩消息偏移量处理

对不同版本的 Client 请求, Broker 会做出不同的判断:对于非 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送不会使用零拷贝技术;而如果是 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送才会使用零拷贝技术







猜你喜欢



0、回复 电子书 获取 本站所有可下载的电子书


1、


2、


3、


4、


5、


6、


7、


8、


9、


10、



11、更多大数据文章欢迎访问https://www.iteblog.com及本公众号(iteblog_hadoop)


12、Flink中文文档:http://flink.iteblog.com












大数据猿(bigdata_ai),专注大数据,关注技术前沿和业界实践,不定期发送大数据相关技术文章、资料以及大数据相关电子书等


推荐阅读
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • Spring Security基础配置详解
    本文详细介绍了Spring Security的基础配置方法,包括如何搭建Maven多模块工程以及具体的安全配置步骤,帮助开发者更好地理解和应用这一强大的安全框架。 ... [详细]
  • 本文将详细介绍如何在Windows 10操作系统中轻松设置本地连接,包括基本步骤和常见问题的解决方案,帮助用户快速掌握操作技巧。 ... [详细]
  • 1、编写一个Java程序在屏幕上输出“你好!”。programmenameHelloworld.javapublicclassHelloworld{publicst ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • 基于SSM框架的在线考试系统:随机组卷功能详解
    本文深入探讨了基于SSM(Spring, Spring MVC, MyBatis)框架构建的在线考试系统中,随机组卷功能的设计与实现方法。 ... [详细]
  • 本文探讨了使用普通生成函数和指数生成函数解决组合与排列问题的方法,特别是在处理特定路径计数问题时的应用。文章通过详细分析和代码实现,展示了如何高效地计算在给定条件下不相邻相同元素的排列数量。 ... [详细]
  • 本文提供了一种有效的方法来解决当Android Studio因电脑意外重启而导致的所有import语句出现错误的问题。通过清除缓存和重建项目结构,可以快速恢复开发环境。 ... [详细]
  • Adobe Flash Player:功能与历史回顾
    本文详细介绍了Adobe Flash Player的功能及其在互联网发展史上的重要角色,同时探讨了其停止支持的原因及后续影响。 ... [详细]
  • 本文详细探讨了在Java中如何将图像对象转换为文件和字节数组(Byte[])的技术。虽然网络上存在大量相关资料,但实际操作时仍需注意细节。本文通过使用JMSL 4.0库中的图表对象作为示例,提供了一种实用的方法。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • CSS Border 属性:solid 边框的使用详解
    本文详细介绍了如何在CSS中使用solid边框属性,包括其基本语法、应用场景及高级技巧,适合初学者和进阶用户参考。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
author-avatar
欣荣_75229
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有