Kafka 集群调优 + 能力探底
一、前言
我们需要对 4 个规格的 kafka 能力进行探底,即其可以承载的最大吞吐;4 个规格对应的单节点的配置如下:
标准版: 2C4G
铂金版: 4C8G
专业版: 8C16G
企业版: 16C32G
另外,一般来讲,在同配置下,kafka 的读性能是要优于写性能的,写操作时,数据要从网卡拷贝至堆内存,然后进行一堆数据校验、解析后,会将数据拷贝至堆外内存,然后再拷贝至操作系统的 page cache,最后操作系统异步刷盘至设备中。而读操作时,kafka 使用了零拷贝技术,数据会从 disk 或 page cache 直接拷贝到网卡,节省了大量的内存拷贝。因此我们这次探底将聚焦于链路的短板,即 kafka 的写操作进行压测
注:本文不是专业的压测报告,而是针对不同集群调优,以获取其最大的吞吐能力
二、磁盘能力探底
在真正开始对 kafka 压测前,我们首先对磁盘的能力进行一个摸底。因为 kafka 是典型的数据型应用,是强依赖磁盘性能的,一旦有了这个数据,那么这个就是 kafka 的性能天花板。如果磁盘是传统的机械磁盘,那么瓶颈毫无悬念一般都会落在磁盘上;但如果磁盘类型是 SSD,而且性能很高的话,操作系统会极力压榨 cpu,从而获取一个最大刷盘吞吐,因此瓶颈在哪就很难讲了
要测试磁盘吞吐的话,2 个变参的影响较大:
单次写入磁盘的数据量
写盘的线程数
2.1、单次刷盘大小
现在的硬件厂商,对于磁盘的优化,基本上都是 4K 对齐的,因此我们的参数一般也要设置为 4K 的整数倍,例如 4K\8K\16K... 如果单次写入量小于 4K,例如只写了 10byte,那么底层刷盘的时候,也会刷 4K 的量,这就是臭名昭著的写放大
而具体单次写多少数据量能达到最优呢? 这就需要不断的 benchmark 了
2.2、刷盘线程数
我们知道 kafka 的 broker 通过参数num.io.threads
来控制 io 的线程数量,通常是 cpu * 2,不过这个参数并不能真实反应在同一时刻写盘的线程数,因此我们探底的时候,也需要动态修改这个参数,从而获取磁盘真实的吞吐
2.3、探底工具
简单描述下这个工具做的事儿:启动 M(可配)个线程,每个线程单次往磁盘中写入 N(可配)K 的数据,整个过程持续 30 秒,然后统计所有写入文件的总大小,最后除以时间,从而计算磁盘吞吐
几个注意点:
大块的磁盘写入,一定要使用
FileChannel
,与 kafka 中的 log 写入对齐
尽量减少 cpu 的使用,将压力下放给磁盘,demo 中使用的 ByteBuffer,通过修改 position 的值模拟大块数据
使用
DirectByteBuffer
,减少一次堆内存 --> 对外内存的拷贝
2C4G
[root@jmc-pod kafka]# java DiskMain 2 4 802 MB/sec
[root@jmc-pod kafka]# java DiskMain 2 8 1016 MB/sec
[root@jmc-pod kafka]# java DiskMain 2 16 1105 MB/sec
[root@jmc-pod kafka]# java DiskMain 2 32 942 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 4 1013 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 8 941 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 16 1062 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 32 1076 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 4 916 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 8 993 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 16 1035 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 32 982 MB/sec
4C8G
[root@jmc-pod kafka]# java DiskMain 2 16 1320 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 4 2172 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 8 2317 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 16 2580 MB/sec
[root@jmc-pod kafka]# java DiskMain 4 32 2271 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 4 2150 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 8 2315 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 16 2498 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 32 2536 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 64 2434 MB/sec
8C16G
[root@jmc-pod kafka]# java DiskMain 4 16 2732 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 4 3440 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 8 3443 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 16 3531 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 32 3561 MB/sec
[root@jmc-pod kafka]# java DiskMain 8 64 3562 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 4 3515 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 8 3573 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 16 3659 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 32 3673 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 64 3674 MB/sec
[root@jmc-pod kafka]# java DiskMain 12 16 3672 MB/sec
16C32G
[root@jmc-pod kafka]# java DiskMain 16 16 3918 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 8 3814 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 32 3885 MB/sec
[root@jmc-pod kafka]# java DiskMain 16 64 3894 MB/sec
[root@jmc-pod kafka]# java DiskMain 24 8 4053 MB/sec
[root@jmc-pod kafka]# java DiskMain 24 16 4039 MB/sec
[root@jmc-pod kafka]# java DiskMain 24 32 4080 MB/sec
[root@jmc-pod kafka]# java DiskMain 24 64 4050 MB/sec
[root@jmc-pod kafka]# java DiskMain 32 16 4042 MB/sec
[root@jmc-pod kafka]# java DiskMain 32 32 4078 MB/sec
通过反复压测,得出如下结论:
在 kafka 3 副本的经典协议下,上述表格便是其吞吐量的天花板。其中 16C32G 在算力上虽然比 8C16G 强了 1 倍,但其落盘速度却基本持平,在大数据的压力下,瓶颈终究会落在磁盘,因此可以大胆预测,其性能不会比 8C16G 高出太多
分析上述数据可知:
2C4G:磁盘的吞吐量约 1G/s,远没有达到上限,此时的瓶颈在 cpu
4C8G:吞吐量虽上升了一倍不止,不过 cpu 飚满,瓶颈还在 cpu
8C16G:吞吐量约为 3.5G/s,相比较 4C8G 并没有翻倍,后端的 cpu 几乎吃满,光看这组数据不好定位瓶颈
16C32G:终于探到磁盘的底了,在 cpu 还有大量剩余的前提下,磁盘明显写不动了
磁盘的性能是真好,居然能压出 4 GB/s 的速率,叹叹
三、Kafka 吞吐量概述
一般描述某个 kafka 集群的吞吐量时,通常写为 3*n MB/
s,例如 3*100 MB/s。 之所以习惯这样描述,是基于 kafka 自身的 3 副本协议,即 1 主 2 备的模式,leader 收到业务流量n
后,2 个 follower 还需要从 leader 将数据同步过来,这样在集群角度看来,是一共处理了3*n
流量
某个 topic 所拥有的副本数,理论上是不能大于整个集群的 broker 数量的,因为副本本质上是做高可用的,当 topic 的副本数大于整个集群的 broker 数量后,那势必某个 broker 存在 2 个及以上副本,这样也就丧失了高可用的初衷
3.1、集群横向扩容
所谓集群横向扩容,是指为集群添加同构 broker,集群的 broker 数量初始为 3,扩容后可能变为了 6,这里的 broker 数量与 topic 的 replica 不是同一个概念,注意区分。
某个 topic 副本数过多,将带来集群内部大量的数据流转,而副本数过少,例如单副本,又存在一些高可用的风险,因此即便随着 broker 数量的增多,kafka 最佳实践还是建议将 topic 的副本数设置为 3,这样每增加 3 个 broker,集群的能力将会得到横向的扩容
这里的横向扩容出来的能力跟 broker 数量是严格呈线性关系的,本文不会对横向扩容进行压测对比
3.2、集群纵向扩容
纵向扩容是指集群的 broker 数量不变,但是提升 broker 的配置。例如之前集群是3 * 2C4G
的规格,进行纵向扩容后,集群将变为3 * 4C8G
broker 的配置线性提升了,其提供的吞吐能力也会随着线性提升吗? 答案是否定的;如果磁盘用的是机械磁盘,我们可能很快能够断言瓶颈将卡在 disk 上,但 SSD 的高吞吐也是非常吃 cpu 的,内容比较复杂,内存、磁盘、cpu 等都息息相关,这里没有很好的捷径,只能 benchmark
纵向压测、对比也是本文的重心
四、发压准备
4.1、客户端准备
4.1.1、发压程序
发压程序使用官方的工具kafka-producer-perf-test.sh
,这个工具实际调用的是 kafka 内核中的类:
当然,单个 Producer 的 pool、开辟内存、与 server 端的连接等都是有上限的,因此真正发压时,需要启动多个发压进程。发压脚本如下
admin5.conf 配置如下(因为开启了 ACL 认证,因此需要申明 SASL 配置)
关于发压脚本的参数配置做一下说明
bootstrap.servers 连接集群的接入点
acks 响应方式,这个对性能影响非常大,这里使用默认的 1。有 3 种配置
1 : leader 收到消息后便返回成功
0 : 不需要等待任何副本确认
-1 : 生产者将等待所有的副本接收到消息并进行确认
buffer.memory 这里是设置了 producer 的 128M 的缓冲区,默认为 32M
producer.config 因为目标集群开启了 acl,这里需要存放一些相关配置
throughput 发送流量的一个上限值,-1 表示不设置上限
num-records 发送消息的条数,因为要压测,所以这里放一个大值
record-size 每条消息的大小。这里配置的 1M,因为需要压测集群的极限值,这里直接设置一个相对大的值
注意,如果消息大小配置较小的话,可以通过调整 batch.size 及 linger.ms 参数来控制攒批
4.1.2、发压机器
因为 kafka 实例是被 k8s 孵化出来的,因此独立开辟了 5 台 ECS 发压,其配置
因为发压程序不会占用大量 cpu 及内存,当开启多进程压测时,只要网络带宽不是瓶颈就 OK
4.2、服务端准备
4.2.1、常规压测配置
集群新建出来后,有一些关键的配置还是需要留意设置一下的,否则性能会打很大的折扣
4.2.2、副本同步
前文说过,kafka 选择不同的副本同步策略、同步副本数量,对性能影响很大;如果选择单副本的话,那么最大吞吐就是上文使用工具测出来的磁盘性能,而如果选择多副本的话,则整体吞吐的计算公式是是业务流量*副本数,后文我们将针对不同acks
、num.replica.fetchers
参数以及不同的副本数分别进行压测,最终得出一个多维参考值
4.2.3、服务端监控
服务端监控主要是查看集群整体流量、broker cpu、内存参数。我们通过 top 命令可以快速获取 cpu、memory 参数,而集群整体流量,为了快速获取,可通过 JMX 去拉取 kafka 原生监控项
每隔 10 秒打印一下集群整体的流量及每个 broker 各自流量,例如:
注意:这里打印的流量,仅包含 leader 处理的业务流量,不包括 follower 从 leader 同步的备份流量,例如,我创建一个单 partition,3 副本的 topic,然后向集群写入 100MB/s 的流量,因为设置了 3 副本,因此虽然只会向其中某个 broker 发送数据,但是另外 2 个 broker 中同时也均会有 100MB/s 的备份流量,但是使用上述工具则只会打印 leader 的流量: [100, 0, 0]
五、发压
5.1、2C4G
5.1.1、单 partition/单副本
最小配置,首先测试一下单 partition、单 replica 的性能,从而与磁盘极限性能做个对比;这个值体现了 kafka 单 broker 的极限能力
创建 topic:【1 partition、1 replica、acks=1】
发压命令
当启动了 8 个 producer 客户端后,监控集群的吞吐峰值来到了 550MB/s;其实启动了 4 个客户端后,吞吐量就达到了 530,后续通过增加客户端数量带来的收益越来越小,说明 broker 端能力已达上限
简单做个对比
在开始对磁盘用工具进行压测时候,2C4G 的规格就因为 cpu 成为了短板,压测工具自身没有消耗 cpu 的逻辑,几乎全量的 cpu 都消耗在了刷盘的操作中
而 kafka 的构成要比磁盘工具复杂很多,涉及内存的数据拷贝、数据解析、正确性验证、刷盘等,而这些操作无疑会消耗大量 cpu,cpu 本身就是短板,因此压测出来的 kafka 吞吐量会比理论值低很多
因此当前 2C4G 的 3 节点的极限能力是 3 * 550MB/s
5.1.2、多 partition/三副本/all acks
当选项 acks 设置为 all 时,代表只有当 3 个副本的消息都落盘后,才会 response,这个设置也是严格的保证了数据的高可用,不会有任何数据的丢失,同时这种配置也是效率最低的,我们创建一个 6 partition,3 副本的 topic,同时将 acks 设置为 all,再查看此时的性能,做一个对比
创建 topic:【6 partition、3 replica、acks=all】
发压命令
启动了 4 个 producer 客户端后,监控集群的吞吐峰值来到了 3 * 320MB/s
4 个客户端的延迟都已经很高,达到了 400ms 左右,说明数据都积攒到了 broker 端排队处理,4 个客户端数据采样:
可见,acks 参数的不同,对最终结果的影响甚大
因 cpu 核数只有 2,因此调整 num.replica.fetchers 参数对最终的压测影响不大,后续等 cpu 核数增加后可以考虑增加此值
5.1.3、多 partition/三副本/leader
然而我们实际生产中,通常既不会将 topic 的副本数设置为 1,也不会将 acks 设置为 all,那么这个时候的最大流量值,体现的便是集群能够处理业务流量的峰值,一旦这个值超过了 550MB/s,那么 follower 一定出现不同程度的落后 leader 的现象,等流量回落后,follower 再逐步进行追赶,因此这个值也是具有相当重要的参考价值
创建 topic:【3 partition、3 replica、acks=1】
发压命令
启动了 12 个 producer 客户端后,监控集群的业务流量峰值来到约了 1GB/s
客户端的延迟都已经达到了 400ms 左右,说明瓶颈不在客户端侧,客户端数据采样:
注意:我这里并没有使用 3 * 1GB/s 的描述,是因为虽然 leader 确实已经接受了 1GB/s 的流量,但是其并没有在同一时刻事实同步给 follower,事实上,随着时间的推移,follower 已经落后的越来越多
5.1.4、整理总结
5.2、4C8G
相关认证配置 admin7.conf
5.2.1、单 partition/单副本
创建 topic:【1 partition、1 replica、acks=1】
当启动了 8 个 producer 端时,集群的流量来到 580 MB/s 左右,这个值与 2C4G 的基本持平,难道它们两个的性能相当吗?其实不尽然,因为单 partition、单副本的 case,注定 broker 将会是同时写入 1 个文件,此时的瓶颈将落在 IO 上,因此,单纯的加 cpu 是不会提升吞吐的
看一下 cpu 的使用率
cpu 基本维持在 180%上下,而 4C 的上限是 400%
5.2.2、multi 【单 partition/单副本】
创建 topic:4 * 【1 partition、1 replica、acks=1】
既然 1 个 topic 无法探知 broker 的上限,那我们就创建多个【单 partition/单副本】的 topic,使其落在同一个 broker 上,然后再向这个 broker 发压即可。(也可以通过手动指定将某个 topic 的分区都分布在 1 台 broker 上实现)
查看 topic_1_1 的 ISR 分布情况:
返回结果
通过这种方式,选取 4 个 topic:topic_1_1、topic_i_1_1、topic_j_1_1、topic_n_1_1,然后每个 topic 启动 4 个 producer 进行发压,也就是一共开启了 16 个 client 端发压
首先看一下 broker 端的流量统计指标,单 broker 的流量来到了 1GB/s
再观察一下 cpu 利用率,维持在 400%,已经打满
客户端的监控日志采样。延迟也高达 500ms,说明压力已经完全给到了 broker
至此,探知当前配置的单 broker 的处理上限为 1 GB/s,因此集群的最大吞吐为 3 * 1 GB/s
5.2.3、多 partition/三副本/all acks
创建 topic:【6 partition、3 replica、acks=-1】
发压命令
吞吐停留在 330 MB/s,怎么跟 2C4G 的相差不大呢?
这里别忘了一个参数 num.replica.fetchers,这个参数默认为 1,调大这个参数将加快 follower 从 leader 拉取数据的速率;我们首先看下当前这个参数的设置:
最终返回
这个参数是可以调用命令进行直接修改的,我们将其修改为 cpu 核数
最终 broker 的性能提升至了 550 MB/s
cpu 利用率也相当低,大量的耗时都停留在三副本 sync 上
5.2.4、多 partition/三副本/leader
将参数“num.replica.fetchers”调整为默认值后,同时将 acks 设置为 1,再次发压
共启动了 16 个客户端,流量来到了 2200 MB/s
同时 cpu 被打满
部分发压程序日志采样。随着 producer 的增多,吞吐量维持在恒定值
5.2.5、整理总结
5.3、8C16G
用到的配置信息 admin6.conf
5.3.1、multi 【单 partition/单副本】
创建 topic:【12 partition、1 replica、acks=1】
通过命令创建 topic,将 12 个分区全部都放在第一个 broker 上
启动 28 个 producer 端发压客户端后,broker 流量趋于稳定
查看对应 pod 的 cpu 使用率,已经打满
最终得出结论,单台 broker 的吞吐上限为 1.9 GB/s
5.3.2、多 partition/三副本/all acks
创建 topic:【12 partition、3 replica、acks=-1】
当前规格配置较高,需要创建更多的 partition 以压榨更多的 cpu 资源
查看参数 num.replica.fetchers
返回
用同样的方法查看参数 replica.fetch.max.bytes,返回
将参数 num.replica.fetchers 修改为 cpu 核数
发压
一共启动了 24 个 producer 压测,强劲的 cpu 发挥了作用,写入速率达到了 950 M/s
5.3.3、多 partition/三副本/leader
创建 topic:【12 partition、3 replica、acks=1】
按照常规,我们压一下三副本写 leader 的 case;此时 num.replica.fetchers 同样设置为 8
启动 28 个压测客户端后,流量趋于稳定
客户端延迟 1s+
broker cpu 使用率接近饱和
至此,可以得出结论,陡增业务流量可承接 3.1 GB/s
5.3.4、整理总结
当前规格,cpu 还是短板,无法触及磁盘的 3.6GB/s
5.4、16C32G
这个配置规格与另外 3 个规格有本质的区别,当前规格在使用磁盘压测工具时,已经窥探到了磁盘的上限,我们继续 benchmark,看它的压测数据。用到的配置信息 admin0.conf
5.4.1、multi 【单 partition/单副本】
创建 topic:【24 partition、1 replica、acks=1】
通过命令创建 topic,将 24 个分区全部都放在第一个 broker 上
启动 35 个 producer 端发压客户端后,broker 流量趋于稳定
查看对应 pod 的 cpu 使用率
最终得出结论,单台 broker 的吞吐上限为 2.7 GB/s
不对啊,这个与预期不符的,单 broker 能力上限的探测,8C16G 已经达到了 1.9G/s,而当前配置预期可以达到 4G/s 的,可无论怎么压,顶多到达 2.7+ GB/s,到底哪里是瓶颈呢?
cpu ? cpu 明显不是瓶颈,当前 broker 的 cpu 使用率还有富余
磁盘? 2.7 GB/s 显然没有达到 disk 的上限,上文已经探知其上限为 4GB/s
发压端? 发压端为了压测最大规格的实例,又额外申请了一个 16C32G 的压测机,而且即便是将客户端数量提升至 40 个,依旧没有变化,甚至可能有小幅度的下掉
既然都不是瓶颈,为什么吞吐上不去呢?难道瓶颈落在了网卡上?
5.4.2、网卡带宽探测--iperf3
这里我们还是很有必要探测一下网卡带宽的上限,使用的压测工具是
「iperf3」
启动 server 端程序
iperf3 -s
这里-s 是-server 的缩写,标明当前启动的是 server 端程序,默认监听 5201 端口
启动 client 端
iperf3 -c 21.100.18.151 -P 8
-c 指启动 client 端,后面的 IP 是 server 端 IP
-P 8 启动并发连接数。这个要额外注意,如果不指定的话,默认是启动 1 个链接测试,这个时候网卡是打不满的,具体设置为多少能打满,需要反复不断测试
当将并发连接数设置为 8 时,达到网络传输的峰值
server 端日志
client 端日志
虽然压测的平均速率是 20.3 Gbits/sec,但其曾经最高速率达到了 22.7 Gbits/sec,因此我们就那这个进行计算。因为这个的单位是 bit,我们需要将其转换为 byte
22.7Gbits/8 = 2.8 GB/s
果然与我们压测的 2.72 GB 对应上了,压力实实在在的给到了网卡
5.4.3、多 partition/三副本/all acks
创建 topic:【24 partition、3 replica、acks=-1】
根据之前的磁盘压测工具已经判断出,当前的规格实例的 cpu 已经不是短板,因此我们这里将 partition 数量设置大一些。另外一些配置的修改
将参数 num.replica.fetchers 修改为 cpu 核数
将参数 replica.fetch.max.bytes 设置为 20M
这样做的目的是加快 follower 同步 leader 数据的速率,经过一段时间发压后,broker 端的速率来到了 1350 MB/s
8C16G 的速率接近 1GB/s,而当前规格虽然配置翻倍了,但是速率却没能翻倍,为什么呢?其实这里也是符合预期的,因为 8C16G 的集群已经非常接近磁盘上限了,压出了 3580 MB/s 的吞吐,而 16C32G 也只能压出 4GB/s 的吞吐,因此瓶颈已经悄悄转移至磁盘上了(acks=all 的情况,很大一部分开销在 3 副本的 sync 上)
其实这里我对不同 partition 的速率也做了压测,这里简单公布结论
5.4.4、整理总结
因为已经将短板确定为网卡,我们这里不再对峰值进行赘述
六、总结
此处我们还是有必要对流量规格再做个说明,以 2C4G 来举例,我们对外宣讲的流量规格是
「 3 * 550 MB/s 」
即集群可以处理 550 MB/s 的吞吐,且在集群内部做好了经典三副本同步,因此站在 partiton leader 的视角,我们脑海中的画面可能是这样的:
而实际结果很有可能是这样的
甚至这样
这取决于 follower 从 leader 的拉取策略,比如参数 num.replica.fetchers、replica.fetch.max.bytes 等的配置,但在磁盘吞吐较高的背景下,又加剧了同步的不稳定性;以下分别以低 IO 及高 IO 进行阐述
低 IO:集群的磁盘吞吐并不高,例如 50 MB/s,集群的吞吐瓶颈会落在了 IO 上,因此当数据进来后会首先进入 page cache 中,然后再由操作系统异步刷盘到磁盘中。因为吞吐不高,因此新数据在 page cache 中存活的时间相对较长,当 follower 从 leader 拉取数据时,数据大概率还在 cache 当中,此时调用 kafka 的零拷贝,将数据 copy 走,性能快,速率稳定,且不占用磁盘 IO
高 IO:就像我们现在部署的集群,IO 的吞吐非常高,拿 2C4G 的规格来讲,单 broker 的写入速率可达 550 MB/s,而内存只有 4 个 G,其中 Java 堆内存又会占用 2.5 个 G,以及操作系统本身的占用,留给 page cache 的空间满打满算也就 1G 左右,那数据进入在 page cache 中停留的时间不会超过 2 秒,等 follower 来拉取数据时,大概率是需要从 disk 设备中进行二次读取的,这就占用了磁盘的带宽,也让整个拉取的过程变得相对不稳定
但我们同样测出了 acks=all 场景中,流量的一个相对精确的保底值,供大家参考
总结各规格集群吞吐如下
测试多规格 kafka 集群的极限吞吐是一个艰巨的任务,其中至少涉及
网络
cpu
磁盘/网络 IO
kafka 攒批模式/消息体大小
刷盘策略
不同规格的 partition 控制
replica 副本同步策略
发压端控制
网络线程/IO 线程搭配
等等。。
这些环节中,只要有 1 个掉链子,那整个链路的吞吐也会拉胯;另外上述所有 case,Java 堆空间只分配了系统一半的内存,另一半留给了 page cache
文章转载自:昔久
评论