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.mzph.cn/bicheng/10951.shtml

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

相关文章

二维费用背包分组背包

二维费用背包&分组背包 一定要做的

真要这么卷?某国产大模型定价下调90%,百万 tokens 只需 1 元!

就在刚刚,国内明星AI公司——智谱AI官宣重磅炸弹: 将能力对标GPT3.5-Turbo的GLM-3的大模型API调用价格最高下调90%,价格仅为原来的十分之一! 废话不多说,直接上图: 官网地址:https://open.big…

机器视觉技术精准测量点胶高度与宽度:提升生产质量的新利器

在现代化生产线中,点胶工艺是许多产品制造过程中的重要环节。点胶的高度和宽度直接影响到产品的质量和性能。传统的测量方法往往效率低下、精度不高,而机器视觉技术的引入,为点胶高度和宽度的测量带来了革命性的变革。本文将探讨机器视觉如何…

Linux 操作系统MySQL 数据库1

1.MySQL 数据库 数据库是“按照数据结构来组织、 存储和管理数据的仓库”。 是一个长期存储在计算机内的、 有组织的、 可共享的、 统一管理的大量数据的集合。 它的存储空间很大, 可以存放百万条、 千万条、 上亿条数据。 但是数据库并不是随意地将数据进行…

【Qt 学习笔记】Qt常用控件 | 容器类控件 | Group Box的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 容器类控件 | Group Box的使用及说明 文章编号&#xff…

测试萌新三天速通python基础(二)列表,字符串,元组,字典,遍历,容器,集合,函数

python基础 字符串下标(索引)切片字符串的替换 replace()字符串拆分 split()字符串的连接 join列表 list列表的增删改查列表的反转 reverse()排序列表嵌套元组 tuple 排序 升序降序交换变量字典 dict查询遍历容器集合函数参数函数的嵌套调⽤函数的返回值模块导⼊的⽅法____name…

【FFmpeg】Filter 过滤器 ② ( 裁剪过滤器 Crop Filter | 裁剪过滤器语法 | 裁剪过滤器内置变量 | 裁剪过滤器常用用法 )

文章目录 一、裁剪过滤器1、裁剪过滤器简介2、裁剪过滤器语法3、裁剪过滤器内置变量4、裁剪过滤器示例5、裁剪过滤器应用6、裁剪过滤器图示 二、裁剪过滤器常用用法1、裁剪指定像素的视频区域2、裁剪视频区域中心正方形 - 默认裁剪3、裁剪视频区域中心正方形 - 手动计算4、裁剪…

【Linux】轻量级应用服务器如何开放端口 -- 详解

一、测试端口是否开放 1、测试程序 TCP demo 程序(可参考:【Linux 网络】网络编程套接字 -- 详解-CSDN博客) 2、测试工具 Windows - cmd 窗口 输入命令:telnet [云服务器的公网ip] [port] 二、腾讯云安全组开放端口 1、安全组设…

【C++】——string类

前言 在C语言里面我们用的字符串都是以\0结尾的字符合集,为了操作方便所以在c中推出了stirng类 一 string介绍 1.string是表示字符串的字符串类 2.因为是类,所以他会有一些常用的接口,同时也添加了专门用来操作string的常规操作 3.string…

揭秘高效引流获客的艺术:转化技巧大公开

在数字化营销的海洋中,每个企业都如同一艘努力航行的船,而流量便是推动船只前行的风帆。如何有效吸引并获取潜在客户,即所谓的“引流获客”,已成为企业市场营销策略中不可或缺的一环。本文将详细探讨几种实用且高效的引流获客技巧…

Ardupilot开源代码之Rover上路 - 后续1

Ardupilot开源代码之Rover上路 - 后续1 1. 源由2. 问题汇总2.1 问题1:飞控选择2.2 问题2:飞控安装位置和固定2.3 问题3:各种插头、插座配套2.4 问题4:分电板缺陷2.5 问题5:电机编码器接线及正反向问题2.6 问题6&#x…

【C++】stack和queue 适配器

🔥个人主页:北辰水墨 🔥专栏:C学习仓 本节内容我们来讲解栈和队列的模拟实现,文末会赋上模拟实现的代码 一、stack的使用和模拟实现 stack适配器的介绍: 1. stack是一种容器适配器,专门用在具…

基于openEuler22.03 LTS环境的容器项目实训——分布式微服务项目部署

一、说明 本文配置环境为VMware虚拟机(4核CPU,4 GB内存,40GB磁盘),OS为openEuler 22.03 LTS ,虚拟机要求能联网。 二、安装docker环境 2.1 安装docker相关软件包 [rootnode01 ~]# dnf -y install docker…

Windows环境下VSCode加MinGw-W64搭建C/C++开发环境

前言: 本文记录了自己在配置 Windows环境下 VSCode,并安装MinGW-W64来搭建windows操作系统下下的C/C开发环境。本文重点参考了如下链接中知乎上的文章里介绍的方法,在windows上安装 MinGW-W64。 vscode c/c环境配置(MinGW&…

深度学习中的一些概念

训练术语 欠拟合 欠拟合是指模型没有很好地捕获到数据特性,不能完整地表示数据的全部信息,也就是模型的复杂度低于应有的水平。例如,假设一个数据集实际上服从二阶多项式分布,但我们使用一阶线性模型去拟合它,这样的…

开发时如何快速分析代码和生成测试方法(Baidu Comate插件帮我一键分析)

目录 前言 Baidu Comate智能编码助手简介 安装教程 使用RabbitMQ一个绑定队列方法进行演示 进行测试现有功能 使用感觉 测试结果 前言 因为在开发代码的时候,发现有很多都是废话也不是很想写注释 的,毕竟程序员最讨厌的两件事情,一…

AI 重塑产品设计

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Chrome的常用操作总结

Chrome的常用操作总结 最近的自己真的好忙啊,好久真好久没有写博客了,今天我就趁着周末的这段时间总结一下最近自己的用的Chrome浏览器常用的命令 不得不说: 就是特么的丝滑!吊打一切浏览器(不接受反驳哈哈哈)因为反驳我也不听嘻嘻 用好快捷键,就是事半功倍!!!重要的事儿说一遍…

【定制化】在Android平台实现自定义的程序启动页

特别说明:以下仅适用于Android平台。 实现原理 创建安卓端自定义的Activity禁用UnityPlayerActivity的启动Logo改用自定义Activity 示例效果 参考简单步骤或详细步骤都可实现。 自定义的启动动画,效果如下: 简单步骤 三步操作实现启动动画…

Vue3项目Easy云盘(二):文件列表+新建目录+文件重命名+文件上传

一、文件列表 1.封装全局组件Table.vue 因为Main.vue等都会用到文件列表table&#xff0c;所以直接封装成组件。 src/components/Table.vue <template><!-- 表格 --><div><el-tableref"dataTable":data"dataSource.list || []":h…