「轻阅读」高并发几十万的写入,Kafka是如何实现的?

代码界的吴彦祖 2019-12-11 17:17:16 ⋅ 545 阅读

原文地址:https://www.toutiao.com/i6768817833418686988

开篇

在初识kafka 一文中讲了使用MQ(消息队列)来设计系统带来的好处:业务解耦、流量削峰、灵活扩展

当下流行的MQ有很多,因为我们公司在技术选型上选择了使用Kafka,所以我就整理了一篇关于Kafka的入门知识。通过技术选型 我们对业界主流的MQ进行了对比,Kakfa最大的优点就是吞吐量高 。

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

那么Kafka是如何做到这么高的吞吐量和性能的呢?在入门之后我们就来深入的扒一下Kafka的架构设计原理,掌握这些原理在互联网面试中会占据优势

持久化

Kafka对消息的存储和缓存依赖于文件系统,每次接收数据都会往磁盘上写,人们对于“磁盘速度慢”的普遍印象,使得人们对于持久化的架构能够提供强有力的性能产生怀疑。

事实上,磁盘的速度比人们预期的要慢的多,也快得多,这取决于人们使用磁盘的方式。而且设计合理的磁盘结构通常可以和网络一样快。


通过上图对比,我们可以看出实际上顺序磁盘访问在某些情况下比随机内存访问还要快,其实Kafka就是利用这一优势来实现高性能写磁盘

See:http://kafka.apachecn.org/documentation.html#persistence

页缓存技术 + 磁盘顺序写

Kafka 为了保证磁盘写入性能,首先Kafka是基于操作系统的页缓存来实现文件写入的。

操作系统本身有一层缓存,叫做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有那么高的性能,做到每秒几十万的吞吐量。

名词解释

  • 吞吐量(TPS):吞吐量是指对网络、设备、端口、虚电路或其他设施,单位时间内成功地传送数据的数量(以比特、字节、分组等测量)



全部评论: 0

    我有话说:

    “12306”如何支撑百QPS

    ! 12306 抢票,极限并发带来思考 虽然现在...

    阅读」大众点评如何分表分库

    原大众点评订单单表早就已经突破两百G,由于查询维度较多,即使加了两个从库,优化索引,仍然存在很多查询不理想

    Nginx服务器高性能优化--轻松实现10并发访问量

    作者:章为忠学架构https://www.toutiao.com/i6804346550882402828 前面讲了如何配置Nginx虚拟主机,如何配置服务日志等很多基础内容,大家可以去这里看看

    阅读如何构建可伸缩Web应用?

    可伸缩性已经成为Web应用程序DNA!

    阅读」推荐系统中信息增强小技巧

    实用推荐系统构建经验,如何进行信息增强。

    阅读」Dubbo 如何成为连接异构微服务体系最佳服务开发框架

    实现异构微服务体系间共存或迁移,关键点在打通异构体系间协议与服务发现,得益于 Dubbo 自身对多协议、多注册模型支持

    转载:Kafka可用,吞吐量低延迟并发特性背后实现机制

    1 概述 Kafka最初由Linkedin公司开发,一个分布式、分区、多副本、多订阅者,基于zookeeper协调分布式消息系统,Linkedin于2010年贡献给了Apache基金会并

    阅读如何设计移动端屏适配方案

    在众多移动设备中,前端开发人员如何在不同屏幕大小,不同程度清屏下去百分百还原设计稿,从来都不

    阅读」移动端事件穿透原理与解决方案

    本文将带你了解事件穿透及如何实际项目中选择合适方案解决事件穿透问题。

    创业团队如何设计支撑百并发数据库架构?

    我们来聊一下对于一个支撑日活百用户并系统,他数据库架构应该如何设计?

    Kafka系列二

    目的:提供负载均衡,实现系统伸缩性【Sca...

    阅读」“做完”和“做好”区别

    在工作中,“做完”和“做好”虽然仅一字之差,但前者只完成了某项工作,而后者则不仅完成了工作还有一个好

    阅读」从MySQL可用架构看可用架构设计

    可用HA(High Availability)分布式系统架构设计中必须考虑因素之一

    阅读」轻松理解 Kubernetes 核心概念

    Kubernetes 迅速成为云环境中软件部署和管理新标准。

    阅读」美团开源QPS压测结果近5w/s分布式ID生成器leaf调试实战

    大型互联网项目ID要保证全局唯一,一般不在用数据库自带id自增了,一般都会用分布式id生成器。