Kafka效率篇-提升效率三板斧

kafka在效率上做了很多的努力。最初的一个使用场景是处理网页上活跃的数据,它往往有非常大的体量,每个页面都能产生数十条写入。而且我们假设每条消息都会被至少一个消费者消费(通常是多个),因此,我们努力让消费变得更加的简单。

我们发现,从构建和运行一定数量的类似的系统的经验来看,消费的效率是有效的多租户运营的关键。假如下游基础设施服务由于应用系统的略微使用就会很容易达到瓶颈,那么很小的变动通常会产生问题。通过效率变得更高,我们可以确保应用系统在相当的负载下,会比下游基础设施更早出问题。这句话的意思就是,kafka系统作为基础设施,会比应用系统更加能抗压力。当你尝试运行一个能够容纳数十或成百应用的中心化集群服务,这是非常重要的一点,因为由于使用模式的改变几乎每天都在发生。

上一节讨论了磁盘效率的问题,假如磁盘访问效率低的问题已经被消除,那么在这类系统中还有两个常见的低效问题

  • 许多小型的I/O操作
  • 过多的字节拷贝

低效问题解决

小型的IO操作

先来说小型的IO操作,这类问题发生在客户端和服务端(broker)之间,以及服务端自己的持久化操作。为了避免这个问题,我们的协议是去构建一个抽象的“数据集”的概念,用来组织一批消息。这个操作允许将消息放在一起发送网络请求并且分摊网络往返的开销,而不是说同一时间只发送一条消息。这带来的好处就是:broker端也能够一次性将一块块的消息附加到日志文件中去,而消费者端也能够同时拉取一大块连续的消息。
单条-批量发送

上图简单说明了,通过消息集的方式发送,能够大幅度减少网络请求,增加kafka的吞吐。

但针对单条消息来说,转微批的方式,会产生一定的延时。直接影响的两个参数为:linger.ms + batch.size。

这两个参数,这里有个误区,我先解释下这两个参数分别的作用:

  • linger.ms:它是kafka 生产者的一个配置,用来控制批量发送消息的等待时间,就是说,当我收到一条消息后,我会默认等待linger.ms的时间,才会发送这批消息,默认linger.ms这个参数默认值是0。
  • batch.size:这个参数可能熟悉的人比较多,它也是用来控制批量发送消息的,不过linger.ms控制的是时间,而batch.size控制的是消息的大小,一旦在producer端暂存的消息大小超过了batch.size,那么就会执行send动作,这里的批是按照partition分组的,就是说发往每个partition的大小不能超过batch.size的大小,否则就会直接发送。默认值为:16384byte,即16KB。

问题来了,很多人在kafka调优过程中,会配置batch.size的大小,比如说调整到1MB或2MB。但是此时kafka吞吐并没有变化,这是为什么呢?

其实问题就出现在linger.ms。消息转微批发送这个动作,是由linger.ms和batch.size两个参数来控制的,即只要这两个参数满足一个,就会将这一批消息发送出去。而linger.ms的默认值为0,就意味着,只要来一条消息,就会立马发送,此时batch.size是不会生效的。

题主在压测过程中,将linger.ms调整成100ms,此时整体业务的tps由200提升到350,说明微批生效。(数字不具备参考意义)

因此:想提高一批消息的大小,要同时调整linger.ms和batch.size。

转批式发送之后,发送的网络包更大了,针对磁盘的操作也有更大的磁盘顺序操作,在内存中也是更大的连续内存块了。这一个操作,将上游随机的消息写入转成了顺序写入。

字节拷贝

  另一个低效的操作是字节拷贝。当消息接受的速率较低时,这不会是一个问题,但是假如负载上来之后,影响就会很大。为了避免这个问题,我们在producer、broker、comsumer端都使用了标准的字节消息格式,这意味着在消息传输过程中,不需要做修改。

在broker端,消息日志就是以文件目录的形式保存的,每个文件由一系列的消息集填充,这些消息集以同样的格式被生产者和消费者使用。保持相同的格式允许一个最重要的优化手段:持久日志块的网络传输。 现代linux操作系统提供了一个高度优化的代码路径,用于将数据从页缓存传输到socket。在操作系统中,这个操作是由sendfile这个系统调用完成的。

在理解sendfile之前,我们先了解一下一般的数据是怎么从文件传输到socket:

  1. 操作系统从磁盘中读取数据并写入到内核空间的页缓存中去
  2. 应用系统将数据从内核区读取到用户空间下的缓冲区
  3. 应用系统将修改后的数据写回到内核空间,并写入到socket缓冲区。
  4. 操作系统将数据从socket 缓冲区拷贝到NIC 缓冲区并发送到网络

下图解释了传统数据的拷贝流程:

在这里插入图片描述

下图描述了文件传输到socket产生的上下文切换:

在这里插入图片描述

以上能看出来明显的低效,其中涉及到四次数据拷贝以及两次系统调用。而使用sendfile,避免了重复的拷贝动作,并且允许操作系统直接将数据从页缓存发送到网络中去,在这个优化下,只会存在一次CPU级别的拷贝动作(页缓存-NIC缓冲区)以及一次系统调用(sendfile)。

先粗略介绍一下零拷贝的使用,可以通过调用transferTo()方法,其底层就是使用了sendfile。

public void transferTo(long position, long count, WritableByteChannel target);

下图表示了使用sendfile之后,我们发送文件需要的代价:

在这里插入图片描述

细节内容,建议大家看官网的解释:

https://developer.ibm.com/articles/j-zerocopy/

我们期望的用户使用场景为一个topic多个消费者,这种场景下,使用了零拷贝之后,数据只需要被拷贝到页缓存,并且就能够被每个消费者重复使用了,而不是将数据保存在内存中并且每次读取都需要拷贝到用户空间去。这就允许消息的消费速率几乎能够达到网络的速率,也就是说此时网络带宽是我们消息系统的瓶颈(压测调优过程中,往往也是以带宽打满为标准)。

页缓存和sendfile的组合意味着在消费者连接的kafka集群中,你看不到磁盘的读取动作,数据几乎都会存在于缓存中。当然异常场景下也会有一些性能问题,这里我举个栗子:

  • 假如测试利用脚本启动了大量的消费者,并且消费大量无关的topic,导致了broker所在的机器上,cache被大量的占用了,此时,真正有效的topic数据,可能会由于内存淘汰策略,已经被刷入到磁盘中去了,这就导致了真正需要用到的topic的数据,每次消费,都需要从磁盘中读取了。

以上是一个真实的案例。

TLS/SSl操作只能在用户空间,目前kafka还不支持内核态的SSL_sendfile。由于这个限制,假如开启了SSL,那么sendfile就会失效。

可以通过以下两个配置开启SSL:

  • security.protocol
  • security.inter.broker.protocol

端到端批量压缩机制

上面有提到,在压测过程中,往往瓶颈不是cpu或内存,而是带宽。这个对于需要在两个数据中心之间传输的场景尤为明显。当然用户可以一个一个的压缩待发送的消息,但是这就造成很低的压缩比。

因为大部分数据的冗余,都是因为重复性,可能由于相同的类型或者json报文中相同的key。有效的压缩操作,最好需要压缩大量的消息而不是单条单条的压缩。

Kafka支持高效的批处理格式,一批消息可以被归在一起,压缩然后发送给服务端(broker)。服务端为了校验这批消息,会解压这批数据。例如说会校验这批消息的数量是否与请求头中消息数保持一致(验证消息是否丢失)。这批消息会以压缩的格式保存在服务端,在服务器日志中会保留压缩的形式并且以同样的形式发送到消费者端。因此消费者端需要以相同的解压缩协议对消息进行解压。

目前kafka支持的压缩协议有:GZIP、Snappy、LZ4和ZStandard。其中GZIP是比较推荐的。

总结

总结一下本文的大致内容,主要解释了kafka如何提高效率的,主要解决了小型IO和大量的字节拷贝问题。

  • 小型IO的问题,kafka的解法是转微批的方式。
  • 字节拷贝问题,kafka利用了零拷贝技术实现,减少了数据的重复拷贝问题,但目前还没做到真正的“零拷贝”。
  • 利用压缩技术,使的网络带宽能够更高效的使用。
  • 后续会出一个关于零拷贝的文章(先埋个坑)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML【常用的标签】、CSS【选择器】

day45 HTML 继day44,w3cschool 常用的标签 k) 表格 表格由 table 标签来定义。每个表格均有若干行(由 tr 标签定义),每行被分割为若干单元格(由 标签定义)。字母 td指表格数据(table data&…

Linux线程(二)线程互斥

目录 一、为什么需要线程互斥 二、线程互斥的必要性 三、票务问题举例(多个线程并发的操作共享变量引发问题) 四、互斥锁的用法 1.互斥锁的原理 2、互斥锁的使用 1、初始化互斥锁 2、加锁和解锁 3、销毁互斥锁(动态分配时需要&#…

【BUUCTF】Crypto_RSA(铜锁/openssl使用系列)

【BUUCTF】Crypto_RSA(铜锁/openssl使用系列) 1、题目 在一次RSA密钥对生成中,假设p473398607161,q4511491,e17 求解出d作为flga提交 2、解析 RSA加密过程: 1)选择素数:选择两个不…

Zabbix监控中文乱码问题解决方法

一、问题描述 1.查看Zabbix仪表盘 在Zabbix的监控仪表盘界面,字体显示为“方框”,无法查看到具体的性能指标名称。 2.问题分析 Zabbix的web端没有中文字库,导致切换到中文页面,中文成了乱码这个问题,我们最需要把中文…

服务器远程桌面局域网连接不上的解决方法

在企业网络环境中,服务器远程桌面局域网连接不上是一个常见且棘手的问题。这种问题可能导致工作效率下降,甚至影响业务运营。因此,我们需要采取专业的方法来解决这一问题。 服务器远程桌面局域网连接不上的解决方法: 1、确保服务器…

Qt服务器端与客户端交互

Qt做客户端与服务器端交互第一步引入network 第一步引入network后继续编程首先界面设计 创建server和socket 引入QTcpServer&#xff0c;QTcpSocket MainWindow.h代码如下 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTcpServer&…

Cisco WLC 2504控制器重启后所有AP掉线故障-系统日期时间

1 故障描述 现场1台WLC 2504控制器掉电重启后&#xff0c;所有AP均无线上线&#xff0c; 正常时共有18个AP在线&#xff0c;而当前为0 AP在线数量为0 (Cisco Controller) >show ap sumNumber of APs.................................... 0Global AP User Name..........…

LeetCode 106.从中序与后序遍历序列构造二叉树

LeetCode 106.从中序与后序遍历序列构造二叉树 1、题目 题目链接&#xff1a;106. 从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并…

SSM【Spring SpringMVC Mybatis】——Mybatis

目录 1、初识Mybatis 1.1Mybatis简介 1.2 官网地址 2、搭建Mybatis框架 2.1 准备 2.2 搭建Mybatis框架步骤 1. 导入jar包 2. 编写核心配置文件【mybatis-config.xml】 3. 书写相关接口及映射文件 4. 测试【SqlSession】 2.3 添加Log4j日志框架 导入jar包 编写配置文…

hive日常使用时忘记部分补充(不定时)

1、date_formate、unix_timestamp、from_unixtime用法&#xff1a; 2、lag&#xff08;&#xff09;、lead()用法&#xff1a; lag&#xff08;)窗口函数返回分区中当前行之前行&#xff08;可以指定第几行&#xff09;的值。 如果没有行&#xff0c;则返回null。 lead()窗口…

搭建Docker私服镜像仓库Harbor

1、概述 Harbor是由VMware公司开源的企业级的Docker Registry管理项目&#xff0c;它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。 Harbor 的所有组件都在 Dcoker 中部署&#xff0c;所以 Harbor 可使用 Docker Compose 快速部署。 …

C++ | Leetcode C++题解之第80题删除有序数组中的重复项II

题目&#xff1a; 题解&#xff1a; class Solution { public:int removeDuplicates(vector<int>& nums) {int n nums.size();if (n < 2) {return n;}int slow 2, fast 2;while (fast < n) {if (nums[slow - 2] ! nums[fast]) {nums[slow] nums[fast];slo…

C++:类与对象—继承

类与对象—继承 一、继承是什么&#xff1f;二、继承定义三、基类和派生类对象赋值转换四、继承中的作用域五、派生类的默认成员函数六、继承与友元七、继承与静态成员八、复杂的菱形继承及菱形虚拟继承九、继承的总结和反思十、考察重点 一、继承是什么&#xff1f; 继承(inh…

Flutter-Statewidget 创建State过程State<XXXX> createState() => _XXXXState()的解释

文章目录 创建widget 的状态对象示例代码解析 完整的代码示例总结 创建widget 的状态对象 今天有个同学问了我下State createState() > _XXXXState()时什么意思。这个代码在flutter开发中一直看到&#xff0c;很多人都不关心这个&#xff0c;直接当模板使用。今天来介绍下这…

[Cmake Qt]找不到文件ui_xx.h的问题?有关Qt工程的问题,看这篇文章就行了。

前言 最近在开发一个组件&#xff0c;但是这个东西是以dll的形式发布的界面库&#xff0c;所以在开发的时候就需要上层调用。 如果你是很懂CMake的话&#xff0c;ui_xx.h的文件目录在 ${CMAKE_CURRENT_BINARY_DIR} 下 然后除了有关这个ui_xx.h&#xff0c;还有一些别的可以简…

如何选择合适加密软件来保护信息资产|精选加密软件分析

五款加密软件对比分析&#xff0c;是一项复杂而必要的任务&#xff0c;旨在帮助用户选择最适合其需求的加密工具。在数字化时代&#xff0c;信息安全显得尤为重要&#xff0c;因此&#xff0c;对加密软件的评估与比较显得尤为关键。 首先&#xff0c;我们要考虑的是这些加密软件…

【2024亚马逊云科技峰会】Amazon Bedrock + Llama3 生成式AI实践

在 4 月 18 日&#xff0c;Meta在官网上公布了旗下最新大模型Llama 3。目前&#xff0c;Llama 3已经开放了80亿&#xff08;8B&#xff09;和700亿&#xff08;70B&#xff09;两个小参数版本&#xff0c;上下文窗口为8k&#xff0c;据称&#xff0c;通过使用更高质量的训练数据…

考情分析 | 2025年西北工业大学计算机考研考情分析!

西北工业简称西工大&#xff08;英文缩写NPU&#xff09;&#xff0c;大学坐落于古都西安&#xff0c;是我国唯一一所以同时发展航空、航天、航海工程教育和科学研究为特色&#xff0c;以工理为主&#xff0c;管、文、经、法协调发展的研究型、多科性和开放式的科学技术大学。十…

使用Selenium破解滑动验证码的原理及解决思路

1、获取页面元素信息&#xff1a; 使用Selenium打开目标网页&#xff0c;并通过相关方法获取滑块、背景图等元素的位置和属性信息。可以使用Selenium提供的定位方法&#xff08;如xpath、CSS选择器等&#xff09;来找到这些元素。 可以使用find_element_by_xpath或find_elemen…

Wix打包后安装包直接签名安装失败原因

生成的游戏启动器wix安装包直接打包后进行签名安装会失败&#xff0c;看安装日志显示的错误为 Failed to extract all files from container, erf: 1:2:0 网上搜到的解决方案 需要用insignia工具解包&#xff0c;解包后的文件签一次名&#xff0c;再打一次包&#xff0c;再…