八大步骤带你深度剖析 Kafka 生产级容量评估方案
The following article is from 华仔聊技术 Author 王江华
本篇章会通过场景驱动的方式来深度剖析 Kafka 生产级容量评估方案如何分析、申请和实施。
1. Kafka 容量评估需求场景分析
集群如何每天 Hold 住 10 亿+ 请求
拿电商平台为例,Kafka 集群每天需要承载 10亿+ 请求流量数据。一天 24 小时,对于平台来说,晚上 12 点到凌晨 8 点这 8 个小时几乎没多少数据涌入的。
这里我们使用「二八法则」来进行预估,也就是 80% 的数据(8 亿)会在剩余的 16 个小时涌入。且 8 亿中的 80% 的数据(约 6.4 亿)会在这 16 个小时的 20% 时间 (约 3 小时)涌入。
通过上面的场景分析,可以得出如下:
QPS = 640000000 ÷ (3 * 60 * 60) = 6万
也就是说,高峰期集群需要抗住每秒 6 万的并发请求。
假设每条数据平均按 20KB(生产端有数据汇总)来算,那就是
1000000000 * 20kb = 18T
一般情况下我们都会设置 3 个副本,即 54T。
另外,Kafka 数据是有保留时间周期的。一般情况是保留最近 3 天的数据,即
54T * 3 = 162T
场景总结
要搞定 10亿+ 请求,高峰期要支撑 6万 QPS,需要大约 162T 的存储空间 。
2. Kafka 容量评估之物理机数量
物理机 OR 虚拟机
一般对于 Kafka、MySQL、Hadoop 等集群自建的时候都会使用物理机来进行搭建,性能和稳定性相对虚拟机要强很多。
在第一步中我们分析得出,系统高峰期的时候要支撑 6万 QPS。如果公司资金和资源充足,一般会让高峰期的 QPS 控制在集群总承载 QPS 能力的 30% 左右。这样可以得出集群能承载的总 QPS 能力约为 20 万左右, 这样系统才会是安全的。
场景总结
根据经验可以得出每台物理机支撑 4万 QPS 是没有问题的。从 QPS 角度分析, 我们要支撑 10亿+ 请求,大约需要 5 台物理机, 考虑到消费者请求,需要增加约 1.5 倍机器, 即 7 台物理机。
机械硬盘 vs 固态硬盘SSD
主要区别
SSD 固态硬盘:它的优点是速度快,日常的读写比机械硬盘快几十倍上百倍。缺点是单位成本高,不适合做大容量存储。
HDD 机械硬盘:它的优点是单位成本低,适合做大容量存储,但速度远不如SSD。
首先,SSD 硬盘性能好。主要是指的随机读写能力性能好,非常适合 MySQL 这样的集群,而 SSD 的顺序读写性能跟机械硬盘的性能是差不多的。
我们知道 Kafka 写磁盘是顺序追加写的。所以,对于 Kafka 集群来说,我们使用普通机械硬盘就可以了。
根据第一和第二个步骤计算结果,我们需要 7 台物理机,一共需要存储 162T 数据,大约每台机器需要存储 23T 数据。根据以往经验,一般服务器配置 11 块硬盘。这样,每块硬盘大约存储 2T 的数据就可以了。
另外,为了服务器性能和稳定性,我们一般要保留一部分空间。保守按每块硬盘最大能存储3 T 数据。
场景总结
要搞定 10亿+ 请求,需要7台物理机, 使用普通机械硬盘进行存储, 每台服务器 11 块硬盘, 每块硬盘存储 2T 数据。
Kafka 写磁盘流程及内存分析
1) 从上图可以得出 Kafka 读写数据的流程主要都是基于 OS Cache。所以,基本上 Kafka 都是基于内存来进行数据流转的。这样的话要分配尽可能多的内存资源给 OS Cache。
2) Kafka 的核心源码基本都是用 Scala 和 Java(客户端)写的,底层都是基于 JVM 来运行的。所以要分配一定的内存给 JVM 以保证服务的稳定性。对于 Kafka 的设计,并没有把很多的数据结构存储到 JVM 中。所以根据经验,给 JVM 分配 6~10G 就足够了。
3) 从上图可以看出一个 Topic 会对于多个 partition,一个 partition 会对应多个 segment,一个 segment 会对应磁盘上 4 个 log 文件。
假设我们这个平台总共 100 个 Topic,那么总共有
Partition总数=100 Topic * 5 partition * 3 副本 = 1500 partition
对于 partition 来说实际上就是物理机上一个文件目录,.log就是存储数据文件的,默认情况下一个 .log 日志文件大小为 1G。
4) 如果要保证这 1500 个 partition 的最新的 .log 文件的数据都在内存中,这样性能当然是最好的,需要 1500 * 1G = 1500 G内存。
但是,我们没有必要所有的数据都驻留到内存中。我们只保证 25% 左右的数据在内存中就可以了。这样大概需要 1500 * 250M = 1500 * 0.25G = 375G 内存。
通过第二步分析结果,我们总共需要 7 台物理机, 这样的话每台服务器只需要约 54G 内存,外加上面分析的 JVM 的 10G,总共需要 64G 内存。还要保留一部分内存给操作系统使用,故我们选择 128G 内存的服务器是非常够用了。
场景总结
要搞定 10亿+ 请求, 需要7台物理机, 每台物理机内存选择 128G 内存为主, 这样内存会比较充裕。
CPU Core 分析
我们评估需要多少个 CPU Core,主要是看 Kafka 进程里会有多少个线程。
线程主要是依托多核 CPU 来执行的。如果线程特别多,但是 CPU 核很少,就会导致 CPU 负载很高,会导致整体工作线程执行的效率不高,性能也不会好。所以,我们要保证 CPU Core 的充足,来保障系统的稳定性和性能最优。
我们评估下 Kafka 服务器启动后会有多少线程在跑。其实这部分内容跟 Kafka 超高并发网络架构密切相关。
上图是 Kafka 超高并发网络架构图,从图中我们可以分析得出:
除了上图所列的还有其他一些线程。所以,估算下来一个 Kafka 服务启动后会有 100 多个线程在跑。
场景总结
要搞定 10亿+ 请求, 需要 7 台物理机,每台物理机内存选择 128G 内存,需要 16 个CPU Core(32 个性能更好)。
网卡对比分析
通过上图分析可以得出,千兆网卡和万兆网卡的区别最大之处在于网口的传输速率的不同。千兆网卡的传输速率是 1000Mbps,万兆网卡的则是 10Gbps。万兆网卡是千兆网卡传输速率的 10倍。
性能上讲,万兆网卡的性能肯定比千兆网卡要好。万兆网卡现在主流的是 10G 的,发展趋势正逐步面向 40G、100G 网卡。但还是要根据使用环境和预算来选择投入,毕竟千兆网卡和万兆网卡的性价比区间还是挺大的。
网卡选择分析
根据第一和第二步分析结果,高峰期的时候,每秒会有大约 6 万请求涌入。即每台机器约 1 万请求涌入(60000/7)。每秒要接收的数据大小为:
10000 * 20 kb = 184 M/s
外加上数据副本的同步网络请求,总共需要 184 * 3 = 552M/s。
一般情况下,网卡带宽是不会达到上限的。
对于千兆网卡,我们能用的基本在 700M 左右。通过上面计算结果,千兆网卡基本可以满足,万兆网卡更好。
场景总结
要搞定 10亿+ 请求,需要 7 台物理机, 每台物理机内存选择 128G 内存为主,需要 16 个 CPU Core(32 个性能更好),千兆网卡基本可以满足,万兆网卡更好。
集群部署规划
这里我采用 5 台服务器来构建 Kafka 集群,集群依赖 ZooKeeper。所以,在部署 Kafka 之前,需要部署好 ZooKeeper 集群。
这里我将 Kafka 和 ZooKeeper 部署在了一起。Kafka 集群节点操作系统仍然采用 Centos 7.7 版本,各个主机角色和软件版本如下表所示:
这里需要注意,Kafka 和 ZooKeeper 的版本。默认 Kafka2.11 版本自带的 ZooKeeper 依赖 jar 包版本为 3.5.7,因此 ZooKeeper 的版本至少在 3.5.7 及以上。
下载与安装
Kafka 需要安装 Java 运行环境,你可以点击Kafka官网
(https://kafka.apache.org/downloads)获取 Kafka 安装包。推荐的版本是 kafka_2.11-2.4.1.tgz。
将下载下来的安装包直接解压到一个路径下即可完成 Kafka 的安装。这里统一将 Kafka 安装到 /usr/local 目录下,我以在 kafka-zk1 主机为例,基本操作过程如下:
[root@kafkazk1~]# tar -zxvf kafka_2.11-2.4.1.tgz -C /usr/local
[root@kafkazk1~]# mv /usr/local/kafka_2.11-2.4.1 /usr/local/kafka
这里我创建了一个 Kafka 用户,用来管理和维护 Kafka 集群。后面所有对 Kafka 的操作都通过此用户来完成。
执行如下操作进行创建用户和授权:
[root@kafkazk1~]# useradd kafka
[root@kafkazk1~]# chown -R kafka:kafka /usr/local/kafka
在 kafka-zk1 节点安装完成 Kafka 后,先进行配置 Kafka。等 Kafka 配置完成,再统一打包复制到其他两个节点上。
broker.id=1
listeners=PLAINTEXT://172.16.213.31:9092
log.dirs=/usr/local/kafka/logs
num.partitions=6
log.retention.hours=72
log.segment.bytes=1073741824
zookeeper.connect=172.16.213.31:2181,172.16.213.32:2181,172.16.213.33:2181
auto.create.topics.enable=true
delete.topic.enable=true
num.network.threads=9
num.io.threads=32
message.max.bytes=10485760
log.flush.interval.message=10000
log.flush.interval.ms=1000
replica.lag.time.max.ms=10
Kafka 配置文件修改完成后,接着打包 Kafka 安装程序,将程序复制到其他 4 个节点,然后进行解压即可。
注意:在其他 4 个节点上,broker.id 务必要修改,Kafka 集群中 broker.id 不能有相同的(唯一的)。
启动集群
五个节点的 Kafka 配置完成后,就可以启动了,但在启动 Kafka 集群前,需要确保 ZooKeeper 集群已经正常启动。
接着,依次在 Kafka 各个节点上执行如下命令即可:
[root@kafkazk1~]# cd /usr/local/kafka
[root@kafkazk1 kafka]# nohup bin/kafka-server-start.sh config/server.properties &
[root@kafkazk1 kafka]# jps
21840 Kafka
15593 Jps
15789 QuorumPeerMain
这里将 Kafka 放到后台(deamon)运行。
启动后,会在启动 Kafka 的当前目录下生成一个 nohup.out 文件,可通过此文件查看 Kafka 的启动和运行状态。通过 jps 指令,可以看到有个 Kafka 标识,这是 Kafka 进程成功启动的标志。
9. 总结
整个场景总结
要搞定 10亿+ 请求, 经过上面深度剖析评估后需要以下资源:
至此已经跟大家全面深度剖析了 Kafka 生产环境容量评估方案的方方面面。
- EOF -
推荐阅读 点击标题可跳转3、深度剖析:Kafka 请求是如何处理? 看完这篇文章彻底懂了!
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
点赞和在看就是最大的支持❤️