etcd性能测试
写之前的疑问。
1、很多第三方资料表示,etcd的v3版本之后写入性能达到了10000+,etcd在github的性能测试说明更是达到了40000+的写入,但是在官网首页又说性能在1000+,我对此感到疑惑。
2、我认为由于etcd的全局revison是单调递增的,而且raft协议需要在集群中达成共识,这两项会大大限制etcd的写入能力。前者会让写入性能串行化,后者会增加网络IO方面的开销。而etcd也做了优化策略,为了提升性能会将多个请求打包在一起再执行raft共识。所以我对etcd的写入能力预期是1k – 10k的水平,视机器性能而定。
3、关于github性能测试说明的读取性能表示存疑,在两种读性能测试中 Linearizable (需要共识来完成,防止脏数据)和 Serializable (无需共识,单个节点可提供服务)相比,在单个连接的情况下和性能差了十几倍,但是在100个客户端的情况二者仅相差2倍。
为了试着解答我的这些疑惑,准备了这次测试。
环境准备:
1、到github下载release版本即可,也可以下载源码编译。
2、启动etcd集群,参考了这个文档
3、参照说明开始测试
关于硬件,由于囊中羞涩,使用了本地电脑VMware的Linux虚拟机,物理机配置如下
1、i7 8550u,默认频1.8g hz,睿频最高4g hz
2、内存ddr4 2400,16GB
3、硬盘三星SSD 960 EVO , 读取3200MB/s ,写入1900MB/s
虚拟机和软件配置如下
1、内存 2G
2、硬盘50G
3、2核心CPU
4、CentOs 7.4
5、使用源码编译的 etcd 3.5.0-pre 尝尝鲜
下面开始测试:
写入测试命令如下:
# 假定 IP_1 是 leader, 写入请求发到 leader
benchmark --endpoints={ip1:port1} --conns=1 --clients=1 \
put --key-size=8 --sequential-keys --total=10000 --val-size=256
benchmark --endpoints={ip1:port1} --conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
# 写入发到所有成员
benchmark --endpoints={ip1:port1},{ip2:port2},{ip3:port3} --conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
写入性能测试结果:
Key的数量 | key的大小 | value的大小 | 连接数量 | 客户端数量 | 目标etcd服务器 | 平均写入QPS | 每请求平均延时 |
10k | 8 | 256 | 1 | 1 | leader | 1250 | 0.8ms |
10k | 8 | 256 | 1 | 1 | flower | 650 | 1.5ms |
10k | 8 | 256 | 1 | 1 | all | 840 | 1.2ms |
100k | 8 | 256 | 100 | 1000 | leader | 21361 | 45ms |
100k | 8 | 256 | 100 | 1000 | flower | 20153 | 48ms |
100k | 8 | 256 | 100 | 1000 | all | 21453 | 45.5 |
读取测试命令如下
# Linearizable 读取请求
benchmark --endpoints={ip1:port1},{ip2:port2},{ip3:port3} --conns=1 --clients=1 \
range YOUR_KEY --consistency=l --total=10000
benchmark --endpoints={ip1:port1},{ip2:port2},{ip3:port3} --conns=100 --clients=1000 \
range YOUR_KEY --consistency=l --total=100000
# Serializable 读取请求,使用每个成员然后将数字加起来
for endpoint in {ip1:port1} {ip2:port2} {ip3:port3}; do
benchmark --endpoints=$endpoint --conns=1 --clients=1 \
range YOUR_KEY --consistency=s --total=10000
done
for endpoint in {ip1:port1} {ip2:port2} {ip3:port3}; do
benchmark --endpoints=$endpoint --conns=100 --clients=1000 \
range YOUR_KEY --consistency=s --total=100000
done
读取性能测试结果:
请求数量 | key大小 | value大小 | 连接数量 | 客户端数量 | 目标etcd服务器 | 一致性 | 每请求平均延时 | 平均读取QPS |
10k | 8 | 256 | 1 | 1 | leader | Linearizable | 0.6ms | 1739 |
10k | 8 | 256 | 1 | 1 | leader | Serializable | 0.3ms | 3293 |
10k | 8 | 256 | 1 | 1 | flower | Linearizable | 0.8ms | 1242 |
10k | 8 | 256 | 1 | 1 | flower | Serializable | 0.3ms | 3261 |
100k | 8 | 256 | 100 | 1000 | leader | Linearizable | 25ms | 36583 |
100k | 8 | 256 | 100 | 1000 | leader | Serializable | 20ms | 44659 |
100k | 8 | 256 | 100 | 1000 | flower | Linearizable | 23ms | 39479 |
100k | 8 | 256 | 100 | 1000 | flower | Serializable | 20ms | 44320 |
线性化(Linearizable)读取请求要求联系集群成员的法定数量来获取最新数据,串行化(Serializable)读取请求要快一些,因为单个节点就可以提供服务,但是有可能会提供过期的数据。
测试结束了,当客户端数和连接数为1时数据还是比较准确的,由于我机器配置的问题,多终端数下测试出现了偏差,数据参考意义不高。可以看出以下几点来
1、etcd进步速度很快,和etcd的github介绍的性能相比,我的在单客户端情况下性能和延时都有了100%的提升
2、从单客户端来看,etcd线性化和串行化情况下性能差异较大,有两三倍的差距,主要是和内网其他节点通信导致的,防止返回脏数据
3、在多客户端高并发请求的时候,QPS有大幅提高,但是牺牲了延迟,可以说是另一种时间换空间的策略,将请求缓存之后成批处理(猜测),所以延迟提高了一些,但是QPS有了保障