为什么Kafka如此之快?
共 4498字,需浏览 9分钟
·
2021-06-07 10:51
Kafka 是由 LinkedIn 公司推出的一个高吞吐的分布式消息系统,通俗地说就是一个基于发布和订阅的消息队列,温故而知新,反复学习优秀的框架,定有所获。
应用场景
Kafka 的应用场景如下:
异步解构:在上下游没有强依赖的业务关系或针对单次请求不需要立刻处理的业务。
系统缓冲:有利于解决服务系统的吞吐量不一致的情况,尤其对处理速度较慢的服务来说起到缓冲作用。
消峰作用:对于短时间偶现的极端流量,对后端的服务可以启动保护作用。
数据流处理:集成 spark 做实时数据流处理。
Kafka 拓扑图(多副本机制)
Kafka 核心组件
topic 的分区,一个 topic 可以包含多个 partition,topic 消息保存在各个 partition 上。
由于一个 topic 能被分到多个分区上,给 kafka 提供给了并行的处理能力,这也正是 kafka 高吞吐的原因之一。
partition 物理上由多个 segment 文件组成,每个 segment 大小相等,顺序读写(这也是 kafka 比较快的原因之一,不需要随机写)。
消息在日志中的位置,可以理解是消息在 partition 上的偏移量,也是代表该消息的唯一序号。
同时也是主从之间的需要同步的信息。
管理 kafka 集群,负责存储了集群 broker、topic、partition 等 meta 数据存储,同时也负责 broker 故障发现,partition leader 选举,负载均衡等功能。
服务治理
在 Kafka 中的 Partition 有一个 leader 与多个 follower,producer 往某个 Partition 中写入数据,是只会往 leader 中写入数据,然后数据才会被复制进其他的 Replica 中。
而每一个 follower 可以理解成一个消费者,定期去 leader 去拉消息。而只有数据同步了后,kafka 才会给生产者返回一个 ACK 告知消息已经存储落地了。
具体流程如下:
生产者发生消息给 leader ,这个时候 leader 完成数据存储,突然发生故障,没有给 producer 返回 ack。
通过 ZK 选举,其中一个 follower 成为 leader ,这个时候 producer 重新请求新的 leader,并存储数据。
Kafka 为什么这么快
①顺序写磁盘
Kafka 采用了顺序写磁盘,而由于顺序写磁盘相对随机写,减少了寻地址的耗费时间。(在 Kafka 的每一个分区里面消息是有序的)
②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。
当然 Kafka 也不例外。零拷贝的概念具体这里不作太详细的复述,大致地给大家讲一下这个概念。
这里大致可以发传统的方式发生了 4 次拷贝,2 次 DMA 和 2 次 CPU,而 CPU 发生了4次的切换。
DMA 简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情。
④零拷贝的方式
通过优化我们可以发现,CPU 只发生了 2 次的上下文切换和 3 次数据拷贝。
Linux 系统提供了系统事故调用函数 “sendfile()”,这样系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态。
⑤分区分段
我们上面也介绍过,Kafka 采取了分区的模式,而每一个分区又对应到一个物理分段,查找的时候可以根据二分查找快速定位。这样不仅提供了数据读的查询效率,也提供了并行操作的方式。
⑥数据压缩
Kafka 对数据提供了:Gzip 和 Snappy 压缩协议等压缩协议,对消息结构体进行了压缩,一方面减少了带宽,也减少了数据传输的消耗。
Kafka 安装
①安装 JDK
yum -y list Java*
yum install java-1.8.0-openjdk-devel.x86_64
Java -version
②安装 Zookeeper
tar -zxvf zookeeper-3.4.9.tar.gz
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
# zookeeper内部的基本单位,单位是毫秒,这个表示一个tickTime为2000毫秒,在zookeeper的其他配置中,都是基于tickTime来做换算的
tickTime=2000
# 集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)。
initLimit=10
#syncLimit:集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
# 数据存放文件夹,zookeeper运行过程中有两个数据需要存储,一个是快照数据(持久化数据)另一个是事务日志
dataDir=/tmp/zookeeper
## 客户端访问端口
clientPort=2181
vim ~/.bash_profile
export ZK=/usr/local/src/apache-zookeeper-3.7.0-bin
export PATH=$PATH:$ZK/bin
export PATH
// 启动
zkServer.sh start
下载 Kafka:
https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka-2.8.0-src.tgz
安装 Kafka:
tar -xzvf kafka_2.12-2.0.0.tgzbr
export ZK=/usr/local/src/apache-zookeeper-3.7.0-bin
export PATH=$PATH:$ZK/bin
export KAFKA=/usr/local/src/kafka
export PATH=$PATH:$KAFKA/bin
启动 Kafka:
nohup kafka-server-start.sh 自己的配置文件路径/server.properties &br
作者:何永康,腾讯 CDG 后台研发工程师。
编辑:陶家龙
文章转载:51CTO技术栈
(版权归原作者所有,侵删)
点击下方“阅读原文”查看更多