字节面试官: 让你设计一个MQ每秒要抗几十万并发,怎么做?

2023-05-16

目录

  • 1、页缓存技术 + 磁盘顺序写
  • 2、零拷贝技术
  • 3、最后的总结

这篇文章来聊一下Kafka的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点。

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

那么Kafka到底是如何做到这么高的吞吐量和性能的呢?这篇文章我们来一点一点说一下。


1、页缓存技术 + 磁盘顺序写

首先Kafka每次接收到数据都会往磁盘上去写,如下图所示。

那么在这里我们不禁有一个疑问了,如果把数据基于磁盘来存储,频繁的往磁盘文件里写数据,这个性能会不会很差?大家肯定都觉得磁盘写性能是极差的。

在这里插入图片描述

没错,要是真的跟上面那个图那么简单的话,那确实这个性能是比较差的。

但是实际上Kafka在这里有极为优秀和出色的设计,就是为了保证数据写入性能,首先Kafka是基于操作系统的页缓存来实现文件写入的。

操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。

你在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中。

仅仅这一个步骤,就可以将磁盘文件写性能提升很多了,因为其实这里相当于是在写内存,不是在写磁盘,大家看下图。

在这里插入图片描述

接着另外一个就是kafka写数据的时候,非常关键的一点,他是以磁盘顺序写的方式来写的。也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。

普通的机械磁盘如果你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。

但是如果你是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能本身也是差不多的。

所以大家就知道了,上面那个图里,Kafka在写数据的时候,一方面基于了os层面的page cache来写数据,所以性能很高,本质就是在写内存罢了。


另外一个,他是采用磁盘顺序写的方式,所以即使数据刷入磁盘的时候,性能也是极高的,也跟写内存是差不多的。

基于上面两点,kafka就实现了写入数据的超高性能。

那么大家想想,假如说kafka写入一条数据要耗费1毫秒的时间,那么是不是每秒就是可以写入1000条数据?

但是假如kafka的性能极高,写入一条数据仅仅耗费0.01毫秒呢?那么每秒是不是就可以写入10万条数?

所以要保证每秒写入几万甚至几十万条数据的核心点,就是尽最大可能提升每条数据写入的性能,这样就可以在单位时间内写入更多的数据量,提升吞吐量。


2、零拷贝技术

说完了写入这块,再来谈谈消费这块。

大家应该都知道,从Kafka里我们经常要消费数据,那么消费的时候实际上就是要从kafka的磁盘文件里读取某条数据然后发送给下游的消费者,如下图所示。

那么这里如果频繁的从磁盘读数据然后发给消费者,性能瓶颈在哪里呢?

在这里插入图片描述

假设要是kafka什么优化都不做,就是很简单的从磁盘读数据发送给下游的消费者,那么大概过程如下所示:

先看看要读的数据在不在os cache里,如果不在的话就从磁盘文件里读取数据后放入os cache。

接着从操作系统的os cache里拷贝数据到应用程序进程的缓存里,再从应用程序进程的缓存里拷贝数据到操作系统层面的Socket缓存里,最后从Socket缓存里提取数据后发送到网卡,最后发送出去给下游消费。

整个过程,如下图所示:

在这里插入图片描述

大家看上图,很明显可以看到有两次没必要的拷贝吧!

一次是从操作系统的cache里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操作系统的Socket缓存里。

而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。

所以这种方式来读取数据是比较消耗性能的。

Kafka为了解决这个问题,在读数据的时候是引入零拷贝技术

也就是说,直接让操作系统的cache中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存。

大家看下图,体会一下这个精妙的过程:

在这里插入图片描述

通过零拷贝技术,就不需要把os cache里的数据拷贝到应用缓存,再从应用缓存拷贝到Socket缓存了,两次拷贝都省略了,所以叫做零拷贝。

对Socket缓存仅仅就是拷贝数据的描述符过去,然后数据就直接从os cache中发送到网卡上去了,这个过程大大的提升了数据消费时读取文件数据的性能。

而且大家会注意到,在从磁盘读数据的时候,会先看看os cache内存中是否有,如果有的话,其实读数据都是直接读内存的。

如果kafka集群经过良好的调优,大家会发现大量的数据都是直接写入os cache中,然后读数据的时候也是从os cache中读。

相当于是Kafka完全基于内存提供数据的写和读了,所以这个整体性能会极其的高。


3、最后的总结

通过这篇文章对kafka底层的页缓存技术的使用,磁盘顺序写的思路,以及零拷贝技术的运用,大家应该就明白Kafka每台机器在底层对数据进行写和读的时候采取的是什么样的思路,为什么他的性能可以那么高,做到每秒几十万的吞吐量。

这种设计思想对我们平时自己设计中间件的架构,或者是出去面试的时候,都有很大的帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字节面试官: 让你设计一个MQ每秒要抗几十万并发,怎么做? 的相关文章

  • 基于全景相机的视觉里程计算法研究

    一 视觉里程计 视觉里程计技术首先建立相机的成像模型 xff0c 接着通过标定算法计算相机参数 xff0c 最后建立相邻图像的关联并估计相机运动轨迹 1 1相机在空间中运动的描述 描述相机在三维空间中的运动状态 xff0c 即求解相机在空间
  • 多旋翼无人机组成(小白上路)

    1 无人机组成 1 1 机架 四旋翼最常见的两种机身布局如下图 xff1a 机架指无人机的承载平台 xff0c 通常用轴距衡量机架的大小 xff0c 轴距是指对角线两个螺旋桨的距离 xff0c 一般以mm为单位 xff0c 如F330表示轴
  • freertos创建任务后进入prvStartFirstTask发生HardFault_Handler中断

    在stm32f103zet6环境中移植成功freertos之后 xff0c 创建第一个任务之后 xff0c 会进入硬件中断 xff0c 经过排查发现死在了prvStartFirstTask 排查原因 xff1a 发现是启动文件startup
  • 解决无法对docker容器进行端口映射的问题

    初学docker的时候 xff0c 不知道为啥 xff0c 按着教程里打的代码 xff0c 最后却出现了映射失败的情况 即 xff1a 在docker内部设置的映射端口 xff0c 外部却没有办法访问 想了想 xff0c 不外乎两个原因 x
  • K8s手工创建kubeconfig

    我们通过 kubectl 命令行连接 k8s apiserver 时需要依赖 kubeconfig 文件 kubeconfig 文件通常包含了 context xff08 上下文 xff09 列表 xff0c 每个 context 又会引用
  • grep命令总结

    grep命令总结 1 关于 nbsp ps ef grep php grep v grep wc l grep v grep 代表在查询的最终结果中去掉grep命令本身 wc l 标示统计查询到的结果数量 grep常用命令 1 grep n
  • Ubuntu 16.04安装realsense D435i SDK以及realsense-ros

    先直接上一个报错信息 xff0c 折腾了半天才解决 在使用catkin make编译realsense ros时 xff0c 报错 traversing 4 packages in topological order realsense c
  • 关于视觉SLAM的一些常识(纯小白学习笔记)

    本文只是小白对于视觉slam的一个非常泛的介绍 xff0c 对于视觉slam中的数学运算均没有提及 xff0c 适合于对没有接触过视觉slam的新人进行一个简单的科普 作者即小白 xff0c 文章如有错误 xff0c 非常非常非常欢迎指正
  • 使用CubeMX快速搭建FREERTOS

    如何使用STM32快速搭建FREERTOS 小编之前一直使用正点原子家的产品 xff0c 最近准备学习学习TOUCHGFX 要用到HAL 43 RTOS 原子家的使用起来不方便 于是琢磨着使用STM32CUBEMX直接生成FREERTOS
  • 使用DMA+SPI驱动Aliyun Things 上的ST7789H2 LCD屏幕

    目录 前言硬件CUBEMX时钟树GPIOSPI 代码部分LCD驱动中断服务函数测试代码现象 前言 1 xff1a 驱动程序参考自https blog csdn net BearPi article details 104311705 2 x
  • SLAM测试5-YGZ-Stereo-Inertial(GAAS双目视觉ygz -立体惯性SLAM)

    这篇主要测试GAAS开源无人机里用到的一种SLAM算法 xff0c 目的是先对该SLAM算法进行熟悉 xff0c 再开始入手GAAS视觉定位 GIThub上的代码地址为 xff1a https github com gaoxiang12 y
  • Linux之线程条件变量cond

    概念 xff1a 条件变量不是锁 xff0c 要和互斥量组合使用 条件变量就是生产者 生产 完成 xff0c 消费者才能 使用 xff0c 如果没有 产品 xff0c 消费者就会被条件变量cond阻塞等待生产者 生产 xff08 生产者与消
  • Linux之线程-信号量sem_*

    1 概念 信号量可理解为进化版的互斥锁 量 xff0c 允许多个线程访问共享资源 由于互斥锁的力度比较大 xff0c 如果希望在多个线程间对某一对象的部分数据进行共享 xff0c 使用互斥锁是没有办法实现的 xff0c 只能将整个数据对象锁
  • 4、树(中篇)

    前言 前节二叉树只能适用于静态查找 不能实现动态插入 删除等 如何解决以下两个问题 静态查找与动态查找 针对动态查找 数据如何组织 4 1 二叉搜索树 4 1 1 什么是二叉搜索树 二叉搜索树 BST Binary Search Tree
  • SNMP源码分析

    源码下载 http www net snmp org download html 源码目录结构 net snmp程序逻辑 xff08 1 xff09 main主函数 span class token macro property span
  • SNMP Trap的session问题

    1 前言 最近遇到了个问题 xff0c SNMPv3 Trap上报 xff0c 在snmp agent侧修改了用户密码 xff0c 管理站mibbroswer上没有修改trap用户的密码 xff0c 仍然可接收到trap上报消息 通过Wir
  • Rancher RKE K8s 集群 etcd 恢复

    背景 在 Rancher 中基于 RKE 创建的 K8s 集群 xff0c 因为服务器磁盘故障 xff0c 导致 3个 master 节点有2个节点的 etcd 数据文件损坏 xff0c 导致整个集群不可用 etcd 三个节点集群时 xff
  • PIXHAWK飞控固件及代码基础介绍

    PIXHAWK飞控 xff1a 固件 xff1a 开源固件PIXHAWK 软件 xff1a 两套固件代码 xff08 1 xff09 原生固件代码PIX4 xff0c 地面站采用QGC xff08 界面比较合理清晰 xff0c 易做修改 x
  • GAAS 无人机自动驾驶学习(01-使用机载电脑,通过OFFBOARD模式进行控制飞行)

    原文网址 xff1a https gaas gitbook io guide wu ren ji zi dong jia shi xi lie offboard kong zhi yi ji gazebo fang zhen 介绍 xff1
  • 2020-10-30

    Ubuntu nvidia显卡驱动安装 手动安装 xff1a 先在官网下载本机显卡对应支持的驱动 xff0c 一般选择run文件 xff1b 如果开启了nouveau驱动 xff0c 需要禁用 xff1b 进入tyy3命令行窗口 xff0c

随机推荐