大家好,我是武哥。

这是《吃透 MQ 系列》之 Kafka 的第 4 篇,错过前 3 篇的,通过下面的链接一睹为快:

第 1 篇:扒开 Kafka 的神秘面纱

第 2 篇:Kafka 架构设计的任督二脉

第 3 篇:Kafka 存储选型的奥秘

第 3 篇文章我深入剖析了 Kafka 选用「日志文件」作为存储方案的来龙去脉以及背后「磁盘顺序写 + 稀疏索引」的精妙设计思路。

但是,Kafka 能做到单机每秒几十万的吞吐量,它的性能优化手段绝不止这一点。

Kafka 的高性能设计可以说是全方位的,从 Prodcuer 、到 Broker、再到 Consumer,Kafka 在掏空心思地优化每一个细节,最终才做到了这样的极致性能。

这篇文章我想先带大家建立一个高性能设计的思维模式,然后再一探究竟 Kafka 的高性能设计方案,最终让大家更体系地掌握所有知识点,并理解它的设计哲学。

1. 如何理解高性能设计?

我们暂且把 Kafka 抛在一边,先尝试理解下高性能设计的本质。

有过高并发开发经验的同学,对于线程池、多级缓存、IO 多路复用、零拷贝等技术概念早就了然于胸,但是返璞归真,这些技术手段的本质到底是什么?

这其实是一个系统性的问题,至少需要深入到操作系统层面,从 CPU 和存储入手,去了解底层的实现机制,然后再自底往上,一层一层去解密和贯穿起来。

但是站在更高的视角来看,我认为:高性能设计其实万变不离其宗,一定是从「计算和 IO」这两个维度出发,去考虑可能的优化点。

那「计算」维度的性能优化手段有哪些呢?无外乎这两种方式:

1、让更多的核来参与计算:比如用多线程代替单线程、用集群代替单机等。

2、减少计算量:比如用索引来取代全局扫描、用同步代替异步、通过限流来减少请求处理量、采用更高效的数据结构和算法等。

再看下「IO」维度的性能优化手段又有哪些? 可以通过 Linux 系统的 IO 栈图来辅助思考。

图 1:Linux 系统的 IO 栈图

可以看到,整个 IO 体系结构是分层的,我们能够从应用程序、操作系统、磁盘等各个层次来考虑性能优化,而所有这些手段又几乎围绕以下两个方面展开:

1、加快 IO 速度:比如用磁盘顺序写代替随机写、用 NIO 代替 BIO、用性能更好的 SSD 代替机械硬盘等。

2、减少 IO 次数或者 IO 数据量:比如借助系统缓存或者外部缓存、通过零拷贝技术减少 IO 复制次数、批量读写、数据压缩等。

上面这些内容可以理解成高性能设计的「道」,当然绝不是几百字就可以说清楚的,我更多的是抛砖引玉,用另外一个视角来看高并发,给大家一个方向上的指引。

当大家抓住了「计算和 IO」这两个最本质的东西,然后以这两点作为根,再去探究这两个维度分别有哪些性能优化手段?它们的原理又是什么样的?便能一层一层剥开高性能设计的神秘面纱,形成可靠的知识体系。

这种分析方法可用来研究 Kafka,同样可以用来研究我们熟知的 Redis、ES 以及其他高性能的应用系统。

2. Kafka 高性能设计的全景图

有了高性能设计的思维模式后,我们再回到 Kafka 本身进行分析。

前文提到过 Kafka 的性能优化手段非常丰富,至少有 10 条以上的精妙设计,虽然我们可以从计算和 IO 两个维度去联想这些手段,但是要完整地记住它们,似乎也不是件容易的事。

这样就引出了另外一个话题:我们应该选用一条什么样的脉络,去串联这些优化手段呢?

之前的文章做过分析:不管 Kafka 、RocketMQ 还是其他消息队列,其本质都是「一发一存一消费」。

我们完全可以顺着这条主线去做结构化梳理。基于这个思路,便形成了下面这张 Kafka 高性能设计的全景图,我按照生产消息、存储消息、消费消息 3 个模块,将 Kafka 最具代表性的 12 条性能优化手段做了归类。

图 2:Kafka 高性能设计的全景图

有了这张全景图,下面我再挨个分析下每个手段背后的大致原理,并尝试解读下 Kafka 的设计哲学。

3. 生产消息的性能优化手段

我们先从生产消息开始看,下面是 Producer 端所采用的 4 条优化手段。

1、批量发送消息

Kafka 作为一个消息队列,很显然是一个 IO 密集型应用,它所面临的挑战除了磁盘 IO(Broker 端需要对消息持久化),还有网络 IO(Producer 到 Broker,Broker 到 Consumer,都需要通过网络进行消息传输)。

在上一篇文章已经指出过:磁盘顺序 IO 的速度其实非常快,不亚于内存随机读写。这样网络 IO 便成为了 Kafka 的性能瓶颈所在。

基于这个背景, Kafka 采用了批量发送消息的方式,通过将多条消息按照分区进行分组,然后每次发送一个消息集合,从而大大减少了网络传输的 overhead。

看似很平常的一个手段,其实它大大提升了 Kafka 的吞吐量,而且它的精妙之处远非如此,下面几条优化手段都和它息息相关。

2、消息压缩

消息压缩的目的是为了进一步减少网络传输带宽。而对于压缩算法来说,通常是:数据量越大,压缩效果才会越好。

因为有了批量发送这个前期,从而使得 Kafka 的消息压缩机制能真正发挥出它的威力(压缩的本质取决于多消息的重复性)。对比压缩单条消息,同时对多条消息进行压缩,能大幅减少数据量,从而更大程度提高网络传输率。

有文章对 Kafka 支持的三种压缩算法:gzip、snappy、lz4 进行了性能对比,测试 2 万条消息,效果如下:

图 3:压缩效果对比,来源:https://www.jianshu.com/p/d69e27749b00

整体来看,gzip 压缩效果最好,但是生成耗时更长,综合对比 lz4 性能最佳。

其实压缩消息不仅仅减少了网络 IO,它还大大降低了磁盘 IO。因为批量消息在持久化到 Broker 中的磁盘时,仍然保持的是压缩状态,最终是在 Consumer 端做了解压缩操作。

这种端到端的压缩设计,其实非常巧妙,它又大大提高了写磁盘的效率。

3、高效序列化

Kafka 消息中的 Key 和 Value,都支持自定义类型,只需要提供相应的序列化和反序列化器即可。因此,用户可以根据实际情况选用快速且紧凑的序列化方式(比如 ProtoBuf、Avro)来减少实际的网络传输量以及磁盘存储量,进一步提高吞吐量。

4、内存池复用

前面说过 Producer 发送消息是批量的,因此消息都会先写入 Producer 的内存中进行缓冲,直到多条消息组成了一个 Batch,才会通过网络把 Batch 发给 Broker。

当这个 Batch 发送完毕后,显然这部分数据还会在 Producer 端的 JVM 内存中,由于不存在引用了,它是可以被 JVM 回收掉的。

但是大家都知道,JVM GC 时一定会存在 Stop The World 的过程,即使采用最先进的垃圾回收器,也势必会导致工作线程的短暂停顿,这对于 Kafka 这种高并发场景肯定会带来性能上的影响。

有了这个背景,便引出了 Kafka 非常优秀的内存池机制,它和连接池、线程池的本质一样,都是为了提高复用,减少频繁的创建和释放。

具体是如何实现的呢?其实很简单:Producer 一上来就会占用一个固定大小的内存块,比如 64MB,然后将 64 MB 划分成 M 个小内存块(比如一个小内存块大小是 16KB)。

当需要创建一个新的 Batch 时,直接从内存池中取出一个 16 KB 的内存块即可,然后往里面不断写入消息,但最大写入量就是 16 KB,接着将 Batch 发送给 Broker ,此时该内存块就可以还回到缓冲池中继续复用了,根本不涉及垃圾回收。最终整个流程如下图所示:

图 4:Kafka 发送端的流程

了解了 Producer 端上面 4 条高性能设计后,大家一定会有一个疑问:传统的数据库或者消息中间件都是想办法让 Client 端更轻量,将 Server 设计成重量级,仅让 Client 充当应用程序和 Server 之间的接口。

但是 Kafka 却反其道而行之,采取了独具一格的设计思路,在将消息发送给 Broker 之前,需要先在 Client 端完成大量的工作,例如:消息的分区路由、校验和的计算、压缩消息等。这样便很好地分摊 Broker 的计算压力。

可见,没有最好的设计,只有最合适的设计,这就是架构的本源。

4. 写在最后

Kafka 在创造一个以性能为核心导向的解决方案上做得极其出色,它有非常多的设计理念值得深入研究和学习。

考虑篇幅问题,我将 Kafka 的高性能设计分成了上下两篇,下一篇将继续展开阐述剩余 8 条高性能设计手段以及背后的设计思想。

看到这里,我更希望大家能建立起高性能设计的思维模式以及学习方法,这些技巧同样可以帮助你吃透其他高性能的中间件。

大家在看:

入职京东了

破 20000 了!

五年了,我的技术管理成长之路

----------  END  ----------

大家好,我是武哥,前亚马逊工程师,现大厂技术管理者,持续分享个人的成长收获,关注我一定能提升你的视野,让我们一起进阶吧!

Kafka 精妙的高性能设计(上篇)相关推荐

  1. Kafka的高性能设计

    目录 如何理解高性能设计? Kafka 高性能设计的全景图 生产消息的性能优化手段 批量发送消息 消息压缩 高效序列化 内存池复用 存储消息的性能优化手段 IO 多路复用 磁盘顺序写 Page Cac ...

  2. Kafka#4:存储设计 分布式设计 源码分析

    https://sites.google.com/a/mammatustech.com/mammatusmain/kafka-architecture/4-kafka-detailed-archite ...

  3. 后台服务架构高性能设计之道

    "N 高 N 可",高性能.高并发.高可用.高可靠.可扩展.可维护.可用性等是后台开发耳熟能详的词了,它们中有些词在大部分情况下表达相近意思.本序列文章旨在探讨和总结后台架构设计中 ...

  4. SpringBoot2.x 官方推荐缓存框架-Caffeine高性能设计剖析

    概要 Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是Guava Cache的优化加强版,有些文章把Caffeine称为"新一代的缓存& ...

  5. 基于SSD的Kafka应用层缓存架构设计与实现

    Kafka在美团数据平台承担着统一的数据缓存和分发的角色,针对因PageCache互相污染,进而引发PageCache竞争导致实时作业被延迟作业影响的痛点,美团基于SSD自研了Kafka的应用层缓存架 ...

  6. 据说是“缓存之王”? Caffeine高性能设计剖析

    概要 Caffeine[1]是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是 Guava Cache 的优化加强版,有些文章把 Caffeine 称为" ...

  7. Kafka 中的这些设计思想值得一学!

    我们今天来聊一聊Kafka中优秀的设计,希望可以提高你的设计能力.写代码能力! 一.Kafka基础 消息系统的作用 应该大部份小伙伴都清楚,用机油装箱举个例子 所以消息系统就是如上图我们所说的仓库,能 ...

  8. ElasticSearch_12_ES的高性能设计

    文章目录 一.前言 二.数据库搜索和ES搜索 2.1 数据库搜索三个问题 2.2 Elasticsearch 2.2.1 Elasticsearch的两个功能 2.2.2 Elasticsearch的 ...

  9. 【架构设计的艺术】Kafka如何通过精妙的架构设计优化JVM GC问题?

    前言 这篇文章,同样给大家聊一个硬核的技术知识,我们通过Kafka内核源码中的一些设计思想,来看你设计Kafka架构的技术大牛,是怎么优化JVM的GC问题的? 1.Kafka的客户端缓冲机制 首先,先 ...

最新文章

  1. 前core成员迈克·赫恩:BCH社区与2014年的BTC社区非常相似
  2. 在IE6/7下表格td标签没有内容时不显示边框?
  3. 实战SSM_O2O商铺_06logback配置与使用
  4. php ftp 创建文件夹失败,phpftp上传多个文件时失败
  5. 一道面试题,我自己的解法
  6. 你不该错过的2020中国开源年报,填开源开发者问卷,成为国内开源的见证者
  7. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告
  8. !!!!Linux系统开发 系列 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程...
  9. 自动化构建部署之Jenkins安装【Docker容器】
  10. 信息学奥赛一本通 1322:【例6.4】拦截导弹问题(Noip1999)
  11. 蔡高厅老师 - 高等数学阅读笔记 - 03 - 极限(13、14、15、16、17)
  12. ~~试除法分解质因数(附模板题)
  13. 吉林大学计算机学院刘,刘华虓-吉林大学计算机科学与技术学院
  14. 2022届秋招笔试题小结:图
  15. 手工配置Service的过程中。
  16. 【jmeter安装】jmeter下载安装超详细简单步骤
  17. 数据库基础知识(思维导图)
  18. Halcon图像拼接-算法速度优化
  19. 使用css设置div块实现阴影呈现3d效果
  20. 【理想流】程序员的性格和命运

热门文章

  1. Deep Learning(深度学习)学习笔记整理
  2. datawindow技巧
  3. linux net子系统-系统调用层
  4. 简述keepalived和其工作原理,keepalived搭建mysql高可用,vip飘逸,避免单点故障@xinxin
  5. 什么是rootkit
  6. wtc java 代码 tpcall(servicename_WebLogic下WTC Service的配置
  7. 运行tensorflow程序,出现ImportError: cannot import name '_validate_lengths'错误的解决办法
  8. MATLAB APP设计
  9. redis放入对象的几种方式
  10. 电子商城数据库设计思路