Kafka 杂谈

news2024/11/28 5:51:38

概览

什么是 Kafka?

这里先给出结论,我不太希望在解释概念 X 的时候,说到「为了了解 X,我们需要先了解一下 Y」,阅读的人思绪会被迁到另一个地方。既然小标题里说了要解释什么是 Kafka,那么我们就只说什么是 Kafka。

专业点讲,Kafka 是一个开源的分布式事件流的平台。通俗点讲,Kafka 就是一个消息队列。

事件流的定义

这才是一个正常的抛概念的顺序,而不是「我们要了解 Kafka,就需要先了解一下 事件流...」

怎么理解这个事件流呢?拿人来类比的话,你可以简单的把它理解成人的中枢神经系统,它是人体神经系统最主要的部分。中枢神经接收全身各个部位的信息输入,然后再发出命令,让身体执行适当的反应。甚至可以说,神经系统可以控制整个生物的行为。

通过这个类比相信你能够理解件流的重要性。

而切回到技术视角来看,事件流其实就是从各种类型的数据源收取实时数据。对应到我们平时对消息队列的用途来说,可以理解为有很多个不同的、甚至说不同种类的生产者,都能够向同一个 Topic 写入消息。

收集到这些事件流后,Kafka 会将它们持久化起来,然后根据需要,将这些事件路由给不同的目标。也换个角度理解,一个 Topic 中所存放的消息(或者说事件)可以被不同的消费者消费。

事件流的用途

现在我们知道了事件流的重要性,上面也拿中枢神经系统做了对比,我们清楚中枢神经系统可以做些什么,那么事件流呢?它能拿来做啥呢?

举例来说,像我们平时网购东西,上面会显示你的快递现在走到哪里了。这就是通过事件流来实时跟踪、监控汽车、卡车或者船只,在物流、汽车行业这样用的比较多;比如,持续的捕获、分析来自物联网设备或者其他设备的传感器数据;通过监测住院病人的数据,来预测病人的病情变化等等这些。

那这个跟 kafka 有啥关系呢?因为除了这些,还有一个比较重要的用途那就是作为一个数据平台、事件驱动架构的基石,而 Kakfa 刚好就是这么一个平台。

Kafka 由来

这块,之前的文章有过介绍,为了避免赘述我就直接贴过来了

Kafka 最初来自于 LinkedIn,是用于做日志收集的工具,采用Java和Scala开发。其实那个时候已经有 ActiveMQ了,但是在当时 ActiveMQ 没有办法满足 LinkedIn 的需求,于是 Kafka 就应运而生。

在 2010 年底,Kakfa 的0.7.0被开源到了Github上。到了2011年,由于 Kafka 非常受关注,被纳入了 Apache Incubator,所有想要成为 Apache 正式项目的外部项目,都必须要经过 Incubator,翻译过来就是孵化器。旨在将一些项目孵化成完全成熟的 Apache 开源项目。

你也可以把它想象成一个学校,所有想要成为 Apache 正式开源项目的外部项目都必须要进入 Incubator 学习,并且拿到毕业证,才能走入社会。于是在 2012 年,Kafka 成功从 Apache Incubator 毕业,正式成为 Apache 中的一员。

Kafka 拥有很高的吞吐量,单机能够抗下十几w的并发,而且写入的性能也很高,能够达到毫秒级别。而且 Kafka的功能较为简单,就是简单的接收生产者的消息,消费者从 Kafka 消费消息。

既然 Kafka 作为一个高可用的平台,那么肯定需要对消息进行持久化,不然一旦重启,所有的消息就都丢了。那 Kafka 是怎么做的持久化呢?

设计

持久化

当然是磁盘了,并且还是强依赖磁盘

不了解的可能会认为:「磁盘?不就是那个很慢很慢的磁盘?」这种速度级的存储设备是怎么样和 Kafka 这样的高性能数据平台沾上边的?

确实我们会看到大量关于磁盘的描述,就是慢。但实际上,磁盘同时集快、慢于一身,其表现具体是快还是慢,还得看我们如何使用它。

举个例子,我们可能都听过,内存的顺序 IO 是慢于内存的随机 IO 的,确实是这样。磁盘自身的随机 IO 和顺序 IO 也有非常大的差异。比如在某些情况下,磁盘顺序写的速度可能是 600MB/秒,而对于磁盘随机写的速度可能才 100KB/秒,这个差异达到了恐怖的 6000 倍。

对磁盘的一些原理感兴趣可以看看我之前写的文章

Kafka 其实就是用实际行动来告诉我们「Don't fear the filesystem」,现在顺序写、读的性能表现是很稳定的,并且我们的大哥操作系统也对此进行了大量的优化。

了解了持久化,解决了消息的存、取问题,还有什么更重要呢?

效率

当然是效率,持久化能保证你的数据不丢,这可能只做到了一半,如果对消息的处理效率不高,仍然不能满足实际生产环境中海量的数据请求。

举个例子,现在请求一个系统的一个页面都有可能会产生好几十条消息,这个在复杂一些的系统里丝毫不夸张。如果投递、消费的效率不提上去,会影响到整个核心链路。

影响效率的大头一半来说有两个:

  • 大量零散的小 IO
  • 大量的数据拷贝

这也是为啥大家都要搞 Buffer,例如 MySQL 里有 Log Buffer,操作系统也有自己的 Buffer,这就是要把尽量减少和磁盘的交互,减少小 IO 的产生,提高效率。

比如说,Consumer 现在需要消费 Broker 上的某条消息,Broker 就需要将此消息从磁盘中读取出来,再通过 Socket 将消息发送给 Consumer。那通常拷贝一个文件再发送会涉及到哪些步骤?

  • 用户态切换到内核态,操作系统将消息从磁盘中读取到内核缓冲区
  • 内核态切换到用户态,应用将内核缓冲区的数据 Copy 到用户缓冲区
  • 用户态切换到内核态,应用将用户缓冲区的内容 Copy 到 Socket 缓冲区
  • 将数据库 Copy 到网卡,网卡会将数据发送出去
  • 内核态切换到用户态

可能你看文字有点懵逼,简单总结就是,涉及到了 4 次态的切换,4 次数据的拷贝,2次系统调用

红色的是态的切换,绿色的是数据拷贝。

态的切换、数据的拷贝,都是耗时的操作,那 Kafka 是怎么解决这个问题的呢?

其实就是我们常说的零拷贝了,但是不要看到零就对零拷贝有误解,认为就是一次都没有拷贝,那你想想,不拷贝怎么样把磁盘的数据读取出来呢?

所谓的零拷贝是指数据在用户态、内核态之间的拷贝次数是 0

最初,从磁盘读取数据的时候是在内核态。

最后,将读取到的数据发送出去的时候也在内核态。

那读取——发送这中间,是不是就没有必要再将数据从内核态拷贝到用户态了?Linux 里封装好的系统调用 sendfile 就已经帮我们做了这件事了。

简单描述一下:「在从磁盘将数据读取到内核态的缓冲区内之后(也就是 pagecache),直接将其拷贝到网卡里,然后发送。」

这里严格上来说还有 offset 的拷贝,但影响太小可以忽略不就,就先不讨论

你会发现,这里也应证了我上面说的「零拷贝并不是说没有拷贝」。算下来,零拷贝总共也有 2 次态的切换,2 次数据的拷贝。但这已经能大大的提升效率了。

到此为止,我们聊到了消息已经被发送出去了,接下来就是消费者接收到这条消息然后开始处理了。那这部分会有效率问题吗?

答案是肯定的,随着现在的计算机发展,系统的瓶颈很多时候已经不是 CPU 或者磁盘了,而是网络带宽。对带宽不理解的你就把带宽理解成一条路的宽度。路宽了,就能同时容纳更多的车行进,堵车的概率也会小一些。

那在路宽不变的基础上,我们要怎么样跑更多的车呢?让车变小(现实中别这么干,手动狗头)。

换句话说,就是要对发送给 Consumer 的信息进行压缩。并且,还不能是来一条压缩一条,为啥呢?因为同类型的一批消息之间会有大量的重复,将这一批进行压缩能够极大的减少重复,而相反,压缩单条消息效果并不理想,因为你没有办法提取公共冗余的部分。Kafka 通过批处理来对消息进行批量压缩。

Push vs Pull

关于这个老生常谈的问题,确实可以简单的聊聊。我们都知道 Consumer 消费数据,无非就是 pull 或者 push。可能在大多数的情况下,这两个没啥区别,但实际上大多数情况下还是用的 pull 的方式。

那为啥是 pull?

假设现在是采取的 push 的方式,那么当 Broker 内部出现了问题,向 Consumer push 的频率降低了,此时作为消费方是不是只能干着急。想象一下,现在产生了消息堆积,我们确啥也干不了,只能等着 Broker 恢复了继续 push 消息到 Consumer。

那如果是 pull 我们怎么解决呢?我们可以新增消费者,以此来增加消费的速率。当然新增消费者并不总是有效,例如在 RocketMQ 中,消费者的数量如果大于了 MessageQueue 的数量,多出来的这部分消费者是无法消费消息的,资源就被白白浪费了。

Kafka 中的 Partition 也是同理,在新增消费者的时候,也需要注意消费者、Partition 的数量。

除此之外,采用 pull 能使 Consumer 更加的灵活,能够根据自己的情况决定什么时候消费,消费多少。

关于消费

这个问题其实在消息系统里也很经典。

Consumer 从 Broker 里拉取数据消费,那 Consumer 如何知道自己消费到哪儿了?Broker 如何知道 Consumer 消费到哪儿了?双方如何达成共识?

我们假设,Broker 在收到 Consumer 的拉取消息请求并发送之后,就将刚刚发送的消息给删除了,这样 OK 吗?

废话,这当然不行,假设 Broker 把消息发给 Consumer 了,但由于 Consumer 挂了并没有收到这些消息,那这些消息就会丢失。

所以才有了我们都熟悉的 ACK(Acknowlegement)机制,Broker 在将消息发出后,将其标识为「已发送|未消费」,Broker 会等待 Consumer 返回一个 ACK,然后再将刚刚的消息标识为「已消费」。

这个机制在一定程度上解决了上面说的消息丢失的问题,但事情总有双面性, ACK 机制又引入了新的问题。

举个例子,假设 Consumer 收到了、并且正确的消费了消息,但偏偏就是在返回 ACK 时出了问题,导致 Broker 没有收到。则在 Broker 侧,消息的状态仍然是「已发送|未消费」,下次 Consumer 来拉,仍然会拉取到这条消息,此时就发生了重复消费。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场

项目说明 兔兔答题是用户端基于uniapp开发支持多端适配,管理端端采用TypeScriptVue3.jselement-plus,后端采用THinkPHP6PHP8Golang开发的一款在线答题应用程序。 问题反馈 线上预览地址 相关问题可以通过下方的二维码,联系到我。了解更多 …

15.状态模式(State)

UML 意图:允许一个对象在其内部状态改变时改变它的行为,使得对象看起来好像修改了它的类型一样。 Context:定义客户感兴趣的接口; 维护一个ConcreteState子类的实例,这个实例定义当前的状态。 State:定义一…

FPGA原理与结构(0)——目录与传送门

一、 简介 FPGA的设计和软件设计不同,我们所设计的RTL代码最终还是要落实到硬件底层来进行实例化,因此理解硬件底层的内容是很有意义的。 二、可编程逻辑块CLB 可配置逻辑块CLB(Configurable Logic Block)是xilinx系类FPGA的基本…

极验率先推出一键认证安全版,供客户自主免费升级,规避日常运营中的风险盲区

2017年6月1日,互联网服务开始响应《中华人民共和国网络安全法》的要求实施账号实名认证。由此,手机号码成为网络世界最主要的“身份证”,也让本机号码一键认证成为可能。其中,极验是最早的直连三大运营商的五家供应商之一&#xf…

Linux内核分析:输入输出,字符与块设备 31-35

CPU 并不直接和设备打交道,它们中间有一个叫作设备控制器(Device Control Unit)的组件,例如硬盘有磁盘控制器、USB 有 USB 控制器、显示器有视频控制器等。这些控制器就像代理商一样,它们知道如何应对硬盘、鼠标、键盘、显示器的行为。 输入输出设备我们大致可以分为两类…

“深入理解事件处理器、表单综合案例和组件通信“

目录 引言1. Vue的事件处理器2. Vue的表单综合案例3. Vue的组件通信总结 引言 Vue.js是一款流行的JavaScript框架,广泛应用于现代Web开发中。在Vue的世界里,事件处理器、表单综合案例和组件通信是三个重要的主题。本文将深入探讨这些主题,并…

二十二、MySQL联合查询

1、基础概念 (1)语法: select …… from …… union [all] select …… from …… (2)理解: 所谓的联合查询,就是对多个条件查询结果进行联合处理,取其并集。 2、实际操作 &…

AI写作生成器-人工智能技术的工具

众所周知,写作是一项需要时间、思考和创造力的工作。传统的写作过程可能需要作者长时间的积累、思考和修改,才能产生一篇优质的文章。随着AI写作生成器的出现,这一传统写作模式正经历着巨大的改变。 AI写作生成器是一类基于人工智能技术的工…

SpringBoot对Filter过滤器中的异常进行全局处理

前言 今天处理拦截器中的异常时,遇到这样一个问题,我们希望在过滤器中对用户的请求进行判断,如果不符合要求直接抛出异常并在前端展示。但是如果我们直接在过滤器中throw一个异常时,尽管我们使用ControllerAdvice和 ExceptionHan…

一对多映射处理

8.3.1 、collection /** * 根据部门id查新部门以及部门中的员工信息 * param did * return */ Dept getDeptEmpByDid(Param("did") int did);<resultMap id"deptEmpMap" type"Dept"> <id property"did" column"did&quo…

Java21 LTS版本

一、前言 除了众所周知的 JEP 之外&#xff0c;Java 21 还有更多内容。首先请确认 java 版本&#xff1a; $ java -version openjdk version "21" 2023-09-19 OpenJDK Runtime Environment (build 2135-2513) OpenJDK 64-Bit Server VM (build 2135-2513, mixed mo…

Shiro 整合 Web

文章目录 Shiro的Web流程Shiro整合SSMShiro整合SpringBootShiro授权方式过滤器链自定义过滤器注解记住我 Shiro的Web流程 Shiro整合SSM 准备SSM的配置准备经典五张表&#xff08;见Shiro基本使用&#xff09;&#xff0c;完成测试准备Shiro的配置 核心过滤器 <!-- 配置S…

Git学习笔记4

GitHub是目前最火的开源项目代码托管平台。它是基于web的Git仓库&#xff0c;提供公有仓库和私有仓库&#xff0c;但私有仓库是需要付费的。 到Github上找类似的项目软件。 GitLab可以创建免费的私有仓库。 GitLab是利用 Ruby开发的一个开源的版本管理系统&#xff0c;实现一个…

ResFields: 一种即插即用的MLP增容工具

ResFields: 一种即插即用的MLP增容工具 目录 概述 RESFIELDS 理论简介 实验(部分) 2D VIDEO APPROXIMATION1 TEMPORAL NEURAL RADIANCE FIELDS (NERF) 消融实验 环境配置 概述 论文名称: RESFIELDS: RESIDUAL NEURAL FIELDS FOR SPATIOTEMPORAL SIGNALS 作者单位…

基于Yolov8的野外烟雾检测(2):多维协作注意模块MCA,效果秒杀ECA、SRM、CBAM等 | 2023.9最新发布

目录 1.Yolov8介绍 2.野外火灾烟雾数据集介绍 3.MCA介绍 4.训练结果分析 5.系列篇 1.Yolov8介绍 Ultralytics YOLOv8是Ultralytics公司开发的YOLO目标检测和图像分割模型的最新版本。YOLOv8是一种尖端的、最先进的&#xff08;SOTA&#xff09;模型&#xff0c;它建立在先前…

Docker 应用部署

Docker 应用部署 一、部署MySQL 搜索MySQL镜像 拉取MySQL镜像 docker pull mysql:8.0创建容器&#xff0c;设置端口映射&#xff0c;目录映射 # 在root/home/mysql目录下创建MySQL目录用于存储MySQL数据信息 mkdir /root/home/mysql cd /root/home/mysql创建并运行 # 330…

video属性练习,手写controls

<video src"../xxx.mp4"></video><div class"controls"><button id"btnPlay">播放/暂停</button></div><div class"controls" id"progress">进度&#xff1a;<input type&quo…

编译chromium总结

文章目录 一、官方文档二、DEPOT_TOOLS_UPDATE三、少修改subprocess.py里的编码四、运行截图 之前在ubuntu18编译过&#xff0c;这次换win11试一试&#xff0c;成功后我又删了一次&#xff0c;再次编译发现了之前没注意到的点。下面是一些重点和我的实践。 一、官方文档 https…

【MT7628AN】IOT | MT7628AN OpenWRT开发与学习

IOT | MT7628AN OpenWRT开发与学习 时间:2023-06-21 文章目录 `IOT` | `MT7628AN` `OpenWRT`[开发与学习](https://blog.csdn.net/I_feige/article/details/132911634?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132911634…

Python练习之选择与循环

目录 1、编写程序&#xff0c;运行后用户输入4位整数作为年份&#xff0c;判断其是否为闰年。提示&#xff1a;如果年份能被400整除&#xff0c;则为闰年&#xff1b;如果年份能被4整除但不能被100整除也为闰年。2、编写程序&#xff0c;用户从键盘输入小于 1000 的整数&#x…