>简要记录。
Kafka 是比较常用的消息队列,我们都知道 Kafka 的吞吐量很大,即使是普通的服务器,Kafka也可以轻松支持每秒百万级的写入请求,超过了大部分的消息中间件,这种特性也使得Kafka在日志处理等海量数据场景广泛应用。
Kafka 的应用场景如下:
- **异步解构**:在上下游没有强依赖的业务关系或针对单次请求不需要立刻处理的业务。
- **系统缓冲**:有利于解决服务系统的吞吐量不一致的情况,尤其对处理速度较慢的服务来说起到缓冲作用。
- **消峰作用**:对于短时间偶现的极端流量,对后端的服务可以启动保护作用。
- **数据流处理**:集成 spark 做实时数据流处理。
为什么 Kafka 这么快?
主要因为一下几点:
1. 顺序写磁盘
2. Page Cache
3. 零拷贝
4. 零拷贝的方式
5. 分区分段
6. 数据压缩
接下来下挨个介绍~
## **顺序写磁盘**
Kafka 采用了顺序写磁盘,而由于顺序写磁盘相对随机写,减少了寻地址的耗费时间。(在 Kafka 的每一个分区里面消息是有序的)
## **Page Cache**
Kafka 在 OS 系统方面使用了 Page Cache 而不是我们平常所用的 Buffer。Page Cache 其实不陌生,也不是什么新鲜事物。

我们在 Linux 上查看内存的时候,经常可以看到 buff/cache,两者都是用来加速 IO 读写用的,而 cache 是作用于读。
也就是说,磁盘的内容可以读到 cache 里面,这样应用程序读磁盘就非常快。
而 buff 是作用于写,我们开发写磁盘都是,一般如果写入一个 buff 里面再 flush 就非常快。
而 Kafka 正是把这两者发挥到了极致:Kafka 虽然是 scala 写的,但是依旧在 Java 的虚拟机上运行。
尽管如此,Kafka 它还是尽量避开了 JVM 的限制,它利用了 Page cache 来存储,这样躲开了数据在 JVM 因为 GC 而发生的 STW。
另一方面也是 Page Cache 使得它实现了零拷贝,具体下面会讲。
## **零拷贝**
无论是优秀的 Netty 还是其他优秀的 Java 框架,基本都在零拷贝减少了 CPU 的上下文切换和磁盘的 IO。
>**关于[零拷贝](https://zhuanlan.zhihu.com/p/88789697)**
传统的一次应用程请求数据的过程:

这里大致可以发传统的方式发生了 4 次拷贝,2 次 DMA 和 2 次 CPU,而 CPU 发生了4次的切换。
DMA 简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情。
## **零拷贝的方式**

通过优化我们可以发现,CPU 只发生了 2 次的上下文切换和 3 次数据拷贝。
Linux 系统提供了系统事故调用函数 “sendfile()”,这样系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态。
## **分区分段**
我们上面也介绍过,Kafka 采取了分区的模式,而每一个分区又对应到一个物理分段,查找的时候可以根据二分查找快速定位。这样不仅提供了数据读的查询效率,也提供了并行操作的方式。
## **数据压缩**
Kafka 对数据提供了:Gzip 和 Snappy 压缩协议等压缩协议,对消息结构体进行了压缩,一方面减少了带宽,也减少了数据传输的消耗。

Kafka为什么这么快?