首先,恭喜晚舟归航!

开篇

使用MQ(消息队列)来设计系统带来的好处:业务解耦、流量削峰、灵活扩展。Kafka是高吞吐低延迟的高并发、高性能的消息中间件,在大数据领域有极为广泛的运用。配置良好的Kafka集群甚至可以做到每秒几十万、上百万的超高并发写入。那么Kafka是如何做到这么高的吞吐量和性能的呢?我们就来深入的扒一下Kafka的架构设计原理,掌握这些原理在互联网面试中会占据优势。
写入数据时使用的方法:
1 page cache
2 顺序写入
 
读取时使用的方法:
1 page cache
2 零拷贝

持久化

Kafka对消息的存储和缓存依赖于文件系统,每次接收数据都会往磁盘上写,人们对于“磁盘速度慢”的普遍印象,使得人们对于持久化的架构能够提供强有力的性能产生怀疑。
事实上,磁盘的速度比人们预期的要慢的多,也快得多,这取决于人们使用磁盘的方式。而且设计合理的磁盘结构通常可以和网络一样快。
通过上图对比,我们可以看出实际上顺序磁盘访问在某些情况下比随机内存访问还要快,其实Kafka就是利用这一优势来实现高性能写磁盘
 

页面缓存技术 + 磁盘顺序写

Kafka 为了保证磁盘写入性能,首先Kafka是基于操作系统的页缓存来实现文件写入的。
Linux操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。你在写磁盘文件的时候,可以直接写入os cache 中,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把os cache 里的数据真的刷入到磁盘中。
通过上图这种方式可以将磁盘文件的写性能提升很多,其实这种方式相当于写内存,不是在写磁盘
顺序写磁盘
另外还有非常关键的一点,Kafka在写数据的时候是以磁盘顺序写的方式来落盘的,也就是说,仅仅将数据追加到文件的末尾(append),而不是在文件的随机位置来修改数据。
对于普通的机械硬盘如果你要是随机写的话,确实性能极低,这里涉及到磁盘寻址的问题。但是如果只是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能本身是差不多的。
来总结一下: Kafka就是基于页面缓存技术 + 磁盘顺序写 技术实现了写入数据的超高性能。所以要保证每秒写入几万甚至几十万条数据的核心点,就是尽最大可能提升每条数据写入的性能,这样就可以在单位时间内写入更多的数据量,提升吞吐量。

零拷贝技术(zero-copy)

说完了写入这块,再来谈谈消费这块。大家应该都知道,从Kafka里我们经常要消费数据,那么消费的时候实际上就是要从kafka的磁盘文件里读取某条数据然后发送给下游的消费者,如下图所示:
如果Kafka以上面这种方式从磁盘中读取数据发送给下游的消费者,大概过程是:
  1. 先看看要读的数据在不在os cache中,如果不在就从磁盘文件里读取数据后放入os cache;
  2. 接着从操作系统的os cache 里拷贝数据到应用程序进程的缓存里,再从应用程序进程的缓存里拷贝数据到操作系统层面的Socket缓存里,最后从Soket缓存里提取数据后发送到网卡,最后发送出去给下游消费者。
整个过程如下图:
从上图可以看出,这整个过程有两次没必要的拷贝,一次是从操作系统的cache里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操作系统的Socket缓存里。而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。所以这种方式来读取数据是比较消耗性能的。
Kafka 为了解决这个问题,在读数据的时候是引入零拷贝技术。也就是说,直接让操作系统的cache中的数据发送到网卡后传出给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存。
体会一下这个精妙的过程吧
通过零拷贝技术,就不需要把os cache里的数据拷贝到应用缓存,再从应用缓存拷贝到Socket缓存了,两次拷贝都省略了,所以叫做零拷贝。对Socket缓存仅仅就是拷贝数据的描述符过去,然后数据就直接从os cache中发送到网卡上去了,这个过程大大的提升了数据消费时读取文件数据的性能。
而且大家会注意到,在从磁盘读数据的时候,会先看看os cache内存中是否有,如果有的话,其实读数据都是直接读内存的。如果kafka集群经过良好的调优,大家会发现大量的数据都是直接写入os cache中,然后读数据的时候也是从os cache中读。相当于是Kafka完全基于内存提供数据的写和读了,所以这个整体性能会极其的高。

总结

通过学习Kafka的优秀设计,我们了解了Kafka底层的页缓存技术的使用,磁盘顺序写的思路,以及零拷贝技术的运用,才能使得Kafka有那么高的性能,做到每秒几十万的吞吐量。

Reference

 

MQ面试题|Kafka如何实现每秒上百万的高并发写入【转】的更多相关文章

  1. Kafka如何实现每秒上百万的高并发写入

    Kafka是高吞吐低延迟的高并发.高性能的消息中间件,在大数据领域有极为广泛的运用.配置良好的Kafka集群甚至可以做到每秒几十万.上百万的超高并发写入. 那么Kafka到底是如何做到这么高的吞吐量和 ...

  2. 18家大厂Java面试题整理了350道(分布式+微服务+高并发)

    一.性能调优系列 1.Tomcat性能调优 JVM参数调优: -Xms 表示JVM初始化堆的大小, -Xmx表示JVM堆的最大值.这两个值的大小一般根据需要进行设置. 当应用程序需要的内存超出堆的最大 ...

  3. 互联网大厂高频重点面试题 (第2季)JUC多线程及高并发

    本期内容包括 JUC多线程并发.JVM和GC等目前大厂笔试中会考.面试中会问.工作中会用的高频难点知识.斩offer.拿高薪.跳槽神器,对标阿里P6的<尚硅谷_互联网大厂高频重点面试题(第2季) ...

  4. Rabbit MQ 面试题相关

    项目中的MQ: #rabbitmq spring.rabbitmq.host=127.0.0.1 主机 spring.rabbitmq.port=5672 端口 spring.rabbitmq.use ...

  5. 2020-05-25:MQ应用场景、Kafka和rabbit区别?kafka为什么支撑高并发? 来自

    福哥答案2020-05-25: 应用场景:解耦.异步.削峰.区别如下:特性 ActiveMQ RabbitMQ RocketMQ Kafka单机吞吐量 万级,比 RocketMQ.Kafka 低一个数 ...

  6. kafka如何实现高并发存储-如何找到一条需要消费的数据(阿里)

    阿里太注重原理了:阿里问kafka如何实现高并发存储-如何找到一条需要消费的数据,kafka用了稀疏索引的方式,使用了二分查找法,其实很多索引都是二分查找法  二分查找法的时间复杂度:O(logn) ...

  7. MQ在高并发环境下,如果队列满了,如何防止消息丢失?

    1.为什么MQ能解决高并发环境下的消息堆积问题? MQ消息如果堆积,消费者不会立马消费所有的消息,不具有实时性,所以可以解决高并发的问题. 性能比较好的消息中间件:Kafka.RabbitMQ,Roc ...

  8. 高并发架构系列:MQ消息队列的12点核心原理总结

    消息队列已经逐渐成为分布式应用场景.内部通信.以及秒杀等高并发业务场景的核心手段,它具有低耦合.可靠投递.广播.流量控制.最终一致性 等一系列功能. 无论是 RabbitMQ.RocketMQ.Act ...

  9. 8月份21道最新Java面试题剖析(数据库+JVM+微服务+高并发)

    前言 纵观几年来的Java面试题,你会发现每家都差不多.你仔细观察就会发现,HashMap的出现几率未免也太高了吧!连考察的知识点都一样,什么hash碰撞啊,并发问题啊!再比如JVM,无外乎考内存结构 ...

  10. 面试题:Nginx 是如何实现高并发?常见的优化手段有哪些?

    面试题: Nginx 是如何实现并发的?为什么 Nginx 不使用多线程?Nginx常见的优化手段有哪些?502错误可能原因有哪些? 面试官心理分析 主要是看应聘人员的对NGINX的基本原理是否熟悉, ...

随机推荐

  1. 后台返回文件URL,前端下载文件,即使设置文件名,下载的文件名称并不是自己所设置的问题

    1.背景 项目中遇到这么一个问题,上传文件后,后台返回的是一个URL,前端需要通过点击下载这个文件 2.首次处理 当时一看是下载文件,觉得很简单,无非是通过创建a标签来实现,以下是我当时的代码,用的是 ...

  2. 鸿蒙开发 HarmonyOS DevEco Studio 常用快捷键

    前言 做 HarmonyOS 鸿蒙开发离不开 DevEco Studio 开发工具, DevEco Studio 是基于 IntelliJ IDEA Community 开源版本打造,所以默认的快捷键 ...

  3. JMeter 自定义的respCode不是0就报异常

    在实际使用中,后台其实已经对异常的进行了处理,response body 返回来的,都是正常的请求响应: 这个时候,则需要通过 respCode 进行判断该请求是否是有效响应. 如响应报文如下: { ...

  4. MySQL 是否可以用 Docker 容器化?

    容器 容器是为了解决 "在切换运行环境时,如何保证软件能够正常运行",容器是轻量级应用代码包,它包含在任何环境中运行所需的所有元素的软件包.容器可以虚拟化操作系统,包含依赖项,例如 ...

  5. 出现TypeError: float() argument must be a string or a number, not _NoValueType(机器学习 Win11)

    博客地址:https://www.cnblogs.com/zylyehuo/ 如果出现以下报错 则说明是torch.numpy等库的版本不匹配 可以去以下网站寻找匹配的版本 https://mirro ...

  6. Hololens2 开发(仿真器)配置

    博客地址:https://www.cnblogs.com/zylyehuo/ 参考链接 1.hololens 开发(仿真器)环境配置 2.visual studio 2019安装后添加工作负载 3.H ...

  7. Docker for Windows Firewall detected

    安装 Docker for Windows 设置挂载磁盘的时候,出现下面这个错误: 尝试 # 把 vEthernet(DockerNAT) 的网络类型改为 private,默认是 public,还是没 ...

  8. Git 查看修改历史

    # 查看某个文件的 commit 历史日志 1. git log filename # 查看每次提交的diff 2. git log -p filename # git show abe69804bb ...

  9. Spring AI与DeepSeek实战三:打造企业知识库

    一.概述 企业应用集成大语言模型(LLM)落地的两大痛点: 知识局限性:LLM依赖静态训练数据,无法覆盖实时更新或垂直领域的知识: 幻觉:当LLM遇到训练数据外的提问时,可能生成看似合理但错误的内容. ...

  10. ShadowSql之功能简介

    ShadowSql包含sql的绝大多数功能 按可执行功能分为Insert.Delete.Update.Select(SingleSelect).CreateTable.DropTable和Trunca ...