测试环境
一共使用10台现网机器,配置如下,另外,NN、DN 的 JVM 参数也和现网保持一致。
项目 |
数值 |
CPU |
96 核 AMD EPYC 7K62 |
内存 |
256G |
磁盘 |
3.6TB X 12块 |
网卡 |
50Gb(由两块 25Gb 的物理网卡聚合而成) |
集群规模 |
1NN + 9DN |
NN handler count |
256 |
HDFS block Size |
128M |
HDFS 默认副本数 |
3 |
HDFS 最小副本数 |
1 |
HDFS EC 策略 |
RS-6-3-1024k |
HDFS集群版本 |
hadoop-3.2.1 |
测试方法
设计多个场景,在每个场景下分别进行读写测试:
-
写测试,使用 TestDFSIO 连续串行写入100个大小为2GB的文件,统计结果,命令如下:
HADOOP_CLIENT_OPTS="-Xmx10G -Xms10G" bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.8.5.jar TestDFSIO -write -nrFiles 100 -size 2GB
-
读测试,使用 TestDFSIO 连续串行读取100个大小为2GB的文件,统计结果,命令如下:
HADOOP_CLIENT_OPTS="-Xmx10G -Xms10G" bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.8.5.jar TestDFSIO -read -nrFiles 100 -size 2GB
注意:
- 每次执行测试前,都需要执行
sync && echo 3 > /proc/sys/vm/drop_caches
释放文件系统缓存,保证多次测试的独立性。
- 针对 EC 场景,需要分别统计使用 Java 编码库和 Intel ISA-L Native 编码库的性能表现。
- 下面测试结果中的 “耗时” 项指的是整个 TestDFSIO 的执行耗时(包括 MR 任务的提交、结果的分析等等),该耗时仅作参考。真正的结果应以 “平均 IO 速率” 这一项为准。
使用 ISA-L Native 编码库的测试结果
正常写入场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
集群内部3副本写 |
部分本地写 |
307.6 |
710.18 |
集群外部3副本写 |
全部非本地写 |
298.71 |
711 |
集群内部EC写 |
部分本地写 |
283.63 |
735.47 |
集群外部EC写 |
全部非本地写 |
276.58 |
749.65 |
正常读取场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
集群内部3副本读 |
构造全部本地读场景 |
1049.58 |
195.78 |
集群内部3副本读 |
构造部分本地读场景 |
1155.52 |
177.98 |
集群外部3副本读 |
全部非本地读 |
1188.55 |
172.94 |
集群内部EC读 |
部分本地读,注意 EC 从原理上注定无法做到全部本地读 |
253.48 |
819.19 |
集群外部EC读 |
全部非本地读 |
247.45 |
839.99 |
异常读取场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
挂掉1个 DN(但不 Dead),集群外部3副本读 |
全部非本地读 |
1148.54 |
178.92 |
挂掉2个 DN(但不 Dead),集群外部3副本读 |
全部非本地读 |
1171.56 |
175.81 |
挂掉1个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读 |
242.47 |
857.24 |
挂掉2个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读 |
233.46 |
888.65 |
挂掉3个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读,挂掉3个 DN 是 6+3 EC 所能容忍的极限情况 |
233.4 |
889.11 |
使用纯 Java 编码库的测试结果
正常写入场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
集群内部3副本写 |
部分本地写 |
307.6 |
710.18 |
集群外部3副本写 |
全部非本地写 |
298.71 |
711 |
集群内部 EC 写 |
部分本地写 |
884.07 |
232.31 |
集群外部 EC 写 |
全部非本地写 |
898.12 |
228.77 |
正常读取场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
集群内部3副本读 |
构造全部本地读场景 |
1049.58 |
195.78 |
集群内部3副本读 |
构造部分本地读场景 |
1155.52 |
177.98 |
集群外部3副本读 |
全部非本地读 |
1188.55 |
172.94 |
集群内部 EC 读 |
部分本地读,注意 EC 从原理上注定无法做到全部本地读 |
245.46 |
847.28 |
集群外部 EC 读 |
全部非本地读 |
238.48 |
871.69 |
异常读取场景
场景 |
测试点 |
耗时(s) |
平均IO速率(MB/s) |
挂掉1个 DN(但不 Dead),集群外部3副本读 |
全部非本地读 |
1148.54 |
178.92 |
挂掉2个 DN(但不 Dead),集群外部3副本读 |
全部非本地读 |
1171.56 |
175.81 |
挂掉1个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读 |
301.45 |
693.09 |
挂掉2个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读 |
439.48 |
481.91 |
挂掉3个 DN(但不 Dead),集群外部 EC 读 |
全部非本地读,挂掉3个 DN 是 6+3 EC 所能容忍的极限情况 |
640.54 |
325.52 |
客户端机器网络带宽使用率(仅测试使用 ISA-L 加速库的情形)
场景 |
测试点 |
客户端网络带宽使用 |
集群外部3副本写 |
全部非本地写 |
5332.41 Mbps |
集群外部 EC 写 |
全部非本地写 |
9500.64 Mbps |
集群外部3副本读 |
全部非本地读 |
1431.67 Mbps |
集群外部 EC 读 |
全部非本地读 |
5565.13 Mbps |
客户端进程 CPU 使用率(仅测试使用 ISA-L 加速库的情形)
注意:这里的 cpu 使用率使用 top -p $PID 统计得到,是所有 CPU 核的累加使用率,对于一个96核的 CPU 来说,该值最大可以到 9600%.
场景 |
测试点 |
客户端进程 cpu 使用率 |
集群外部3副本写 |
全部非本地写 |
91.7% |
集群外部EC写 |
全部非本地写 |
227.5% |
集群外部3副本读 |
全部非本地读 |
14% |
集群外部EC读 |
全部非本地读 |
88% |
测试结论
- ISA-L Native 加速库非常关键,如果没有这个加速库,EC 写性能仅能达到副本写的 30% 左右。因此,下面所有的结论都针对使用 ISA-L 加速库的情形。
- EC 会显著增加客户端机器的网络带宽和 CPU 消耗,以 6+3 为例,相比正常的3副本:
- 客户端写入过程中,理论上它的带宽使用会增长9倍,但受限于磁盘写入速度、交换机速度等因素,具体增长程度可能较低,本次测试中增长2倍。
- 客户端读取过程中,理论上它的带宽使用会增长6倍,同样,受限于磁盘读取速度、交换机速度等因素,具体增加程度可能较低,本次测试中增长4倍。
- 客户端写入过程中,由于并发写入且需要计算 EC 校验值,其 CPU 使用率会显著增长,本次测试中增长7倍。
- 客户端读取过程中,由于并发读取,其 CPU 使用率也会显著增长,本次测试中增长6倍。
- EC 并不会降低客户端的 IO 速度,反而,在其它关键要素都满足的情况下(主要是 CPU 和 网络),EC 会提升 IO 速度,特别是显著提升读取速度,以 6+3 为例:
- 客户端写入过程中,虽然增加了计算校验值的步骤,但是在 ISA-L 的帮助下,这部分耗时并不多,完全可以被之后的9倍并发写找补回来,在本次测试中,客户端 EC 写入速度比3副本提升了 5% 左右。
- 客户端读取过程中,EC 的6倍并发读完全压过了3副本的单线程读,在本次测试中,EC 读速度比3副本本地读提升了300%,这其中的原因是:单线程读完全受制于磁盘的极限读取速度(190MB/s左右),反观6倍并发读不受此限制。
- EC 在正常读取和修复读取两种情况下,速度差别不大,以 6+3 为例:
- 无论是正常读取还是修复读取,客户端都是固定的6倍并发读6 个 DN,不会随着挂掉的 DN 个数变化而变化。
- 在 ISA-L 帮助下,异常读取时的修复时间(即计算出原始数据的时间)很短。
- 以上的结果都是在网络和 CPU 完全足够的情况下测得的,特别是网络,本次测试中所有机器都配置了一个50Gb 的 bond 网卡(由两张 25Gb 的物理网卡聚合而成),完全够用。但在真实场景下,CPU、网络可能达不到本次测试的理想条件,因此结果也可能会有出入。