前言

天下武功,唯快不破。同样的,kafka在消息队列领域,也是非常快的,这里的块指的是kafka在单位时间搬运的数据量大小,也就是吞吐量,下图是搬运网上的一个性能测试结果,在同步发送场景下,单机Kafka的吞吐量高达17.3w/s,不愧是高吞吐量消息中间件的行业老大。

那究竟是什么原因让kafka如此之快呢?这也是面试官非常喜欢问的问题。

四个原因

原因一:磁盘顺序读写

生产者发送数据到kafka集群中,最终会写入到磁盘中,会采用顺序写入的方式。消费者从kafka集群中获取数据时,也是采用顺序读的方式。

无论是机械磁盘还是固态硬盘SSD,顺序读写的速度都是远大于随机读写的。因为对于机械磁盘顺序读写省去了磁头频繁寻址和旋转盘片的开销。而固态硬盘就更加复杂,这里不展开阐述。

下图是网上关于读写方式的性能比较。

  • 机械磁盘顺序读写 53M/s,随读写 316k/s
  • 固态硬盘顺序读写 42M/s, 随机读写 1000k/s

因而,由于kafka一般使用机械磁盘存储消息,因为机械磁盘的价格远小于固态硬盘SSD。

原因二:PageCache页缓存技术

前面提到了kafka采用顺序读写写入到磁盘中,难道是直接kafka到磁盘吗,实际上不是的,中间多了一道操作系统的PageCache页缓存,可以理解为内存。

  • 当kafka有写操作时,先将数据写入PageCache中,然后在定时方式顺序写入到磁盘中。
  • 当读操作发生时,先从PageCache中查找,如果找不到,再去磁盘中读取。

通过页缓存技术,更近一步的提高了读写的性能。

原因三:零拷贝技术

kafka之所以快的另外一个原因是采用了零拷贝技术。

首先我们来看下从磁盘读取数据到网卡场景下,传统IO的整个过程,如下图所示:

传统IO模型下,从磁盘读取数据,写到网卡设备中,经历了4次用户态和内核态之间的切换,以及4次数据的拷贝,包括CPU拷贝和DMA拷贝。这些操作都是十分损耗性能。

DMA, Direct Memory Access, 直接内存访问是一些计算机总线架构提供的功能,它能使数据从附加设备(如磁盘驱动器)直接发送到计算机主板的内存上。

那能否减少这样的切换和拷贝呢? 答案是肯定的,不知道大家发下没有,kafka的消息在应用层做任何转换,怎么存就怎么取,你看连序列化、反序列化都是在生产者和消费者做的。所以kafka采用了sendfile的零拷贝技术

sendfile零拷贝技术在内核态将数据从PageCache拷贝到了Socket缓冲区,这样就大大减少了不同形态的切换以及拷贝。

所谓的零拷贝技术不是指不发生拷贝,而是在用户态没有进行拷贝。

原因四:kafka分区架构和批量操作

一方面kafka的集群架构采用了多分区技术,并行度高。另外一方面,kafka采用了批量操作。生产者发送的消息先发送到一个队列,然后有sender线程批量发送给kafka集群。

如何提高生产者的吞吐量?

kafka生产者提供的一些配置参数可以有助于提高生产者的吞吐量。

参数名称 描述
buffer.memory RecordAccumulator 缓冲区总大小,默认 32m。适当增加该值,可以提高吞吐量。
batch.size 缓冲区一批数据最大值,默认 16k。适当增加该值,可以提高吞吐量,但是如果该值设置太大,会导致数据传输延迟增加。
linger.ms 如果数据迟迟未达到 batch.sizesender线程等待 linger.time之后就会发送数据。单位 ms,默认值是 0ms,表示没有延迟。生产环境建议该值大小为 5-100ms 之间。
compression.type 指定消息的压缩方式,默认值为“none ",即默认情况下,消息不会被压缩。该参数还可以配置为 "gzip","snappy" 和 "lz4"。对消息进行压缩可以极大地减少网络传输、降低网络 I/O,从而提高整体的性能 。

如何提高消费者的吞吐量?

  1. 如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数 = 分区数,并发度最高
  2. 如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少,使处理的数据小于生产的数据,也会造成数据积压。
  • fetch.max.bytes:默认 Default: 52428800(50 m)。消费者获取服务器端一批消息最大的字节数。如果服务器端一批次的数据大于该值(50m)仍然可以拉取回来这批数据,因此,这不是一个绝、对最大值。一批次的大小受 message.max.bytes (broker config)or max.message.bytes (topic config)影响。
  • max.poll.records:一次 poll 拉取数据返回消息的最大条数,默认是 500
  1. 优化消费者代码处理的逻辑。

总结

本文总结了Kafka为什么快的原因,4个关键字,磁盘顺序读写,页缓存技术,零拷贝技术,Kafka本身分区机制和批量操作。我们抓住这4个关键字,有点到面地和面试官娓娓道来。

Kafka 在性能上确实是一骑绝尘,但在消息选型过程中,我们不仅仅要参考其性能,还有从功能性上来考虑,例如 RocketMQ 提供了丰富的消息检索功能、事务消息、消息消费重试、定时消息等。

通常在大数据、流式处理场景基本选用 Kafka,业务处理相关选择 RocketMQ更佳。

欢迎关注个人公众号【JAVA旭阳】交流学习

面试官问:kafka为什么如此之快?的更多相关文章

  1. 面试官问我,Redis分布式锁如何续期?懵了。

    前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...

  2. 当面试官问我ArrayList和LinkedList哪个更占空间时,我这么答让他眼前一亮

    前言 今天介绍一下Java的两个集合类,ArrayList和LinkedList,这两个集合的知识点几乎可以说面试必问的. 对于这两个集合类,相信大家都不陌生,ArrayList可以说是日常开发中用的 ...

  3. 「干货」面试官问我如何快速搜索10万个矩形?——我说RBush

    「干货」面试官问我如何快速搜索10万个矩形?--我说RBUSH 前言 亲爱的coder们,我又来了,一个喜欢图形的程序员‍,前几篇文章一直都在教大家怎么画地图.画折线图.画烟花,难道图形就是这样嘛,当 ...

  4. 每日一问:面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

    面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

  5. 面试官问,说一个你在工作非常有价值的bug

    如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...

  6. 面试官问:JS的this指向

    前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...

  7. 当面试官问你sql优化的时候。。。

    当面试官问你有关sql优化的问题时,直接拿笔写给他: 8-select 9-distinct<column_list> 1-from left_table 3-<join_type& ...

  8. 面试官问你JS基本类型时他想知道什么?

    面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括:1.基本类型(值类型或者原始类型): Number.Boolean.String.NULL.Undefined以及ES6的Sym ...

  9. 面试官问线程安全的List,看完再也不怕了!

    最近在Java技术栈知识星球里面有球友问到了线程安全的 List: 扫码查看答案或加入知识星球 栈长在之前的文章<出场率比较高的一道多线程安全面试题>里面讲过 ArrayList 的不安全 ...

  10. 美团面试官问我一个字符的String.length()是多少,我说是1,面试官说你回去好好学一下吧

    本文首发于微信公众号:程序员乔戈里 public class testT { public static void main(String [] args){ String A = "hi你 ...

随机推荐

  1. 从pcap文件中提取pcma音频

    操作系统 :Windows10_x64 .CentOS 7.6.1810_x64 wireshark版本:3.6.12 Python 版本  :  3.9.12 一.背景描述 工作中有时候会遇到需要从 ...

  2. 移动端测试辅助工具 - adb

    1. 概念: adb(android debug bridge)是android提供的基于CS架构的命令行调试工具,使PC与安卓设备之间实现通信 2. 基础原理: 交互图: 主要由三部分组成: adb ...

  3. ES6let const

    let const class 类 import 引入模块 export 暴露接口 // var a = 10; // let b = 20; // const c = 30; var和let比 co ...

  4. 保持唯一性,请停止使用【python3 内置hash() 函数】

    问题: 如图,用hash() 筛重时竟然出现了重复. 如下图: hash字符串时,同一窗口的是一致的,不同窗口结果竟然不同. 原因: python的字符串hash算法并不是直接遍历字符串每个字符去计算 ...

  5. Wikijs简介-强大&可扩展的开源维基软件

    Wikijs - 最强大 最可扩展的开源维基软件 使用 wiki.js 美丽直观的界面,让文档成为写作的乐趣! 优点 随时随地安装 几乎适用于任何平台,并与PostgreSQL.MySQL.Maria ...

  6. internal java compiler error

    1.导入Maven项目运行报错:  解决方法:找到File->Settings  修改配置 再次运行就可以了.

  7. JQuery日期选择控件-兼容手机端

    在项目中经常使用到日期时间控件. 用的时候总是临时去找,现在记录下,以备下次使用. 官网http://www.bootcss.com/p/bootstrap-datetimepicker/ 需要引用一 ...

  8. React onBlur回调中使用document.activeElement返回body解决方案

    最开始想实现一个功能,点击img图标后给出购物下拉框CartDropdown,当img及CartDropdown失去焦点时隐藏CartDropdown. 最开始的核心代码如下: export defa ...

  9. javasec(一)java反射

    这篇文章介绍javasec基础知识--java反射. 0x01 反射是什么? 反射是一种机制,利用反射机制动态的实例化对象.读写属性.调用方法.构造函数. 在程序运行状态中,对于任意一个类或对象,都能 ...

  10. C# 控制系统任务栏的显示与隐藏

    [DllImport("user32.dll")] public static extern int FindWindow(string lpClassName, string l ...