网站建设需要注意哪些关键细节,微信小程序购物商城,网页微信版网址,研发一个app费用Kafka在性能方面有着显著的优势#xff0c;这也使得Kafka的应用非常广泛#xff0c;那kakfa的性能为何如此优异呢#xff1f;本文将带你探寻kafka高性能之谜。 kafka的高性能概括起来有如下几点#xff1a;顺序写入磁盘与I/O优化、批量处理、页缓存、零拷贝技术、分区并行处… Kafka在性能方面有着显著的优势这也使得Kafka的应用非常广泛那kakfa的性能为何如此优异呢本文将带你探寻kafka高性能之谜。 kafka的高性能概括起来有如下几点顺序写入磁盘与I/O优化、批量处理、页缓存、零拷贝技术、分区并行处理、高效的消息压缩。下面将分别极少这几方面的内容。
一、顺序写入磁盘与I/O优化 人们对于磁盘速度慢的普遍印象使得人们对于持久化的架构提供强有力的性能产生怀疑。事实上磁盘的速度快慢取决于使用磁盘的方式而且设计合理的磁盘结构通常可以和网络一样快。 关于磁盘性能的关键事实是磁盘的吞吐量和过去十年里磁盘的寻址不同。使用6个7200rpm、SATA接口、RAID-5的磁盘阵列在JBOD配置下的顺序写入的性能约为600MB/s但随机写入的性能仅约为100k/s,相差6000倍以上。因为线性的读取和写入是磁盘使用模式中最有规律的并且由操作系统进行大量的优化现代操作系统提供了read-ahead和write-behind技术。 read-ahead操作系统文件预读linux系统内核将指定文件的某区域预读进页缓存起来便于对该区域进行读取时不会因缺页而阻塞。预读可以有效地减少磁盘的寻址次数和应用程序的I/O等待时间。 write-behind将多个小型的逻辑合并成一次大型的物理磁盘写入。 1.1 数据在kafka中是如何存储的 一个主题对应多个分区每个分区又有多个副本一个副本对应一个日志(Log)为了防止Log过大Kafka又引入了日志分段(LogSegment)将log切分成多个LogSegmnt相当于一个巨型文件被平均分成多个相对较小的文件这样便于消息的维护和清理。 事实上Log和LogSegment也不是纯粹物理意义上的概念Log在物理上只以文件夹的形式存储而每个LogSegment对应于磁盘上一个日志文件和两个索引文件以及可能的其他文件。下图描述了主题、分区与副本、日志之间的关系。 在Log中追加消息时是 顺序写入 的只有最后一个LogSegment才能执行写入操作在此之前所有的LogSegment都不能写入数据。日志中还存在索引文件可以高效的定位消息提高效率。 从这里就能看出日志的内容是顺序写入的所以磁盘的性能比随机写入要好的多这是kafka高性能的第一个原因。 二、批量处理 批量处理提高性能很好理解将多次操作合并为一次操作. 生产者发送消息时支持批量发送消息将多条消息积累到一个批次中然后一次性发送给Kafka Broker这样可以减少网络I/O次数显著提升吞吐量并降低延迟尤其是在网络带宽成为瓶颈时。 在消费者端Kafka也支持批处理的机制。消费者可以在处理完一批消息后一起提交这些消息的偏移量Offset而不是每次消费一条消息就立即提交Offset。这种批量提交策略有助于减少与Kafka Broker之间的通信开销同时也能保证了整体消费进度的一致性。 在broker端可以通过write-behind等技术将多次磁盘操作合并为一个减少刷盘操作。 这是Kafka高性能的第二个原因。 三、页缓存技术 页缓存是操作系统实现的一种主要的磁盘缓存以此用来减少对磁盘I/O的操作。具体来说就是把磁盘中的数据缓存到内存中把对磁盘的访问变为对内存的访问。 当一个进程准备读取磁盘上的文件时操作系统会先查看读取的数据所在的页page是否在页缓存pagecache中如果存在则直接返回数据从而避免了对物理磁盘的I/O操作如果没有命中则操作系统会像磁盘发起读取请求并将读取的数据页存入页缓存之后再将数据返回给进程。同样一个进程需要将数据写入磁盘那么操作系统也会检测数据对应的页是否在页缓存中如果不存在则会先在页缓存中添加相应的页最后将数据写入对应的页。被修改的页也就变成了脏页操作系统会在合适的时间把脏页写入磁盘以保持数据的一致性。 Linux操作系统中vm.dirty_background_ratio参数用来指定当脏页数量达到系统内存的百分之多少后会触发pdflush/flush/kdmflush等后台回写进程的运行来处理脏页。 kafka中大量的使用了页缓存这也是kafka实现高吞吐量的重要因素之一。虽然消息都是先被写入页缓存然后由操作系统负责具体的刷盘任务但在kafka中同样提供了同步刷盘即阶段性强制刷盘fsyc的功能。 这是Kafka高性能的第三个原因。但有一种情况需要引起注意会导致页缓存失效。在kafka出现严重挤压时生产者开始时的确是把消息写入到了页缓存但由于消费者处理速度过慢挤压严重那页缓存中的数据会不断的被置换到磁盘上当消费者消费消息时可能需要从磁盘读取了这对性能是极大的损耗所以要尽量避免kafka出现严重的积压情况。 四、零拷贝技术 磁盘可以说是计算机系统最慢的硬件之一读写速度相差内存10倍以上所以针对磁盘的优化技术非常多比如零拷贝、直接I/O、异步I/O等等这些优化的目的是为了提高系统的吞吐量这里主要介绍零拷贝。 我们以文件传输作为切入点来分析I/O工作方式以及如何优化传输文件的性能。 4.1 DMA 技术 在没有DMA技术前I/O是这样工作的 CPU发出对应的指令给磁盘控制器然后返回磁盘控制器收到指令后开始准备数据会把数据放到磁盘控制器的内部缓冲区中然后产生一个中断CPU收到中断信号后停下手头的工作接着把磁盘控制器的缓冲区的数据一次一个字节地读进自己的寄存器然后再把寄存器里的数据写入到内存而在数据传输的期间CPU无法执行其他任务。 可以看到整个数据传输过程都需要CPU亲自参与搬运数据的过程而且这个过程CPU是不能做其他事情的。简单的搬运几个字符数据是没问题的但是如果我们用千兆网卡或者硬盘传输大量数据的时候都用CPU来搬运的话肯定忙不过来。 于是DMA技术就诞生了也就是直接内存访问Direct Memory Acess技术。简单理解就是DMA方式无需处理器的干预在内存与I/O之间进行快速数据交换。在进行I/O设备的内存的数据传输的时候数据搬运工作全部交给DMA控制器而CPU不在参与任何数据搬运相关的事情这样CPU就可以去处理别的事情。 用户进程调用read方法向操作系统发出I/O请求请求读取数据到自己的内存中进程进入阻塞状态操作系统收到请求后进一步将I/O请求发送到DMA然后让CPU执行其他任务DMA进一步将I/O请求发送给磁盘磁盘收到DMA的I/O请求把数据从磁盘读取到磁盘控制器的缓冲区中当磁盘控制器的缓冲区被读满后向DMA发起中断信号告知自己缓冲区已满DMA收到磁盘的信号将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中此时不占用CPUCPU可以执行其他任务当DMA读取了足够多的数据就会发送中断信号给CPUCPU收到DMA的信号知道数据已经准备好于是将数据从内核拷贝到用户空间系统调用返回。 可以看到整个数据传输过程CPU不在参与数据搬运的工作而是全程由DMA完成但是CPU在这个过程中也是必不可少的因为传输什么数据从哪里传输到哪里都需要CPU来告诉DMA控制器。 4.2 文件传输 如果服务端要提供文件传输功能我们能想到的最简单的方式将磁盘上的文件读取出来然后通过网络协议发送给客户端。 传统I/O的工作方式是数据读取和写入是从用户空间到内核空间来回复制内核空间的数据是通过操作系统层面的I/O接口从磁盘读取或写入的。 首先期间共发生了4次用户态与内核态的上下文切换因为发生了两次系统调用一次是read一次是write每次系统调用都得先从用户态切换到内核态等内核完成任务后再从内核态切换会用户态。 上线文切换成本并不小一次切换需要耗时几十纳秒到几微妙虽然看上去时间很短但是在高并发的场景下这类时间容易被累计放大从而影响系统整体性能。 其次发生了四次数据拷贝其中两次是DMA的拷贝另外两次则是通过CPU拷贝的 第一次拷贝把磁盘上的数据拷贝到操作系统内核的缓冲区里这个拷贝过程是通过DMA搬运的。第二次拷贝把内核缓冲区的数据拷贝到用户的缓冲区里于是我们应用程序就可以使用这部分数据了这个拷贝过程则是由CPU完成的。第三次拷贝把刚拷贝到用户缓冲区里的数据再拷贝到内核socket的缓冲区里这个过程依然是CPU完成的。第四次拷贝把内核socket缓冲区里的数据拷贝到网卡缓冲区里这个过程又是由DMA搬运的。 看这个文件的传输过程我们只是搬运一份数据结果却搬运了4次过多的数据拷贝无疑会消耗CPU资源大大降低系统性能。 这种简单又传统的方式存在冗余的上下文切换和数据拷贝在高并发系统里是非常糟糕的多了很多不必要的开销会严重影响系统性能。所以要想提高文件传输的性能就要减少用户态与内核态的上下问切换与内存拷贝的次数。 4.3 零拷贝 Linux 内核从 2.4 版本开始对于网卡支持SG-DMA技术的情况下sendFile()系统调用的过程发生了变化。 通过DMA将磁盘上的数据拷贝到内核缓冲区中缓冲区描述符和数据长度传输到socket缓冲区这样网卡的SG-DMA控制器就可以直接将内核缓冲区中的数据拷贝到网卡缓冲区里此过程不需要将数据从操作系统内科拷贝到socket缓冲区。 就是所谓的零拷贝技术因为我们没有在内存层面去拷贝数据也就是全程没有通过CPU来搬运数据所有的数据都通过DMA来进行传输。与传统方式相比减少了两次上下文切换和数据拷贝次数只需要两次上下文切换就可以完成文件传输而且两次数据拷贝都不要CPU的参与所以零拷贝技术可以把文件传输的性能提高至少一倍以上。 kafka在数据传输中尽可能减少数据复制环节利用操作系统提供的零拷贝技术将数据直接从文件缓存区传递到网络协议栈降低了CPU开销和延迟。这是kafka高性能的第四个原因。 五、分区并行处理 这个很好理解Kafka将主题拆分为多个分区并且可以在不同的broker节点上分布这些分区实现了并行处理能力从而能够扩展以应对高并发场景下的读写需求。 这是kafka高性能的第五个原因。 六、高效的消息压缩 支持消息压缩功能在不影响消息传递速度的同时降低网络带宽消耗进一步提升整体性能。 常见的压缩算法是数据量越大压缩效果越好一条消息通常不会太大这就导致压缩效果不太好。而Kafka实现的压缩方式是将多条消息一起进行压缩这样可以保证比较好的压缩效果。 producer将消息进行压缩发往brokerbroker保存消息。这里需要注意producer和broker的压缩算法要一致broker端有参数可以配置压缩算法默认值是producer即保持生产者的压缩算法。如果两端的压缩算法不一致producer用一种压缩算法发到broker后 broker需要对压缩消息进行解压解压后在按照broker设置的压缩算法进行压缩然后在保存多了许多额外的操作会导致broker的CPU变高导致吞吐量下降效率降低。消费者与broker有同样的问题。常用的压缩算法有GZIO、SNAPPY、LZ4。 将多条消息进行压缩处理这是kafka高性能的第六个原因。 七、总结 关于kafka高性能的原因就介绍到这里不知道你学会了吗欢迎留言讨论。