这是本节的多页打印视图。 .
基准测试
- 1: 存储内存使用量基准测试
- 2: 监听内存使用量基准测试
- 3: etcd v3 基准测试
- 4: etcd v2.2.0-rc 内存基准测试
- 5: etcd v2.2.0-rc 基准测试
- 6: etcd v2.2.0 基准测试
- 7: etcd v2.1.0 基准测试
基准测试
etcd 性能基准测试结果将定期发布,并在以下各版本中持续追踪:
内存使用基准
它记录了在不同场景下的预期内存使用情况。
1 - 存储内存使用量基准测试
etcd 存储的两个组件会占用物理内存。etcd 进程分配了一个 内存索引,用于加速键的查找。进程的 页缓存 由操作系统管理,用于存储从磁盘读取的最近访问数据,以便快速重用。
内存索引将所有键以 B 树 数据结构的形式存储,并附带指向磁盘数据(即值)的指针。B 树中的每个键可能包含多个指针,指向其值的不同版本。因此,内存索引的理论内存消耗可近似表示为以下公式:
N * (c1 + avg_key_size) + N * (avg_versions_of_key) * (c2 + size_of_pointer)
其中 c1 为键元数据开销,c2 为版本元数据开销。
图表展示了内存中索引 B 树的详细结构。
页面缓存内存 由操作系统管理,本文档不对其进行详细说明。
测试环境
etcd 版本
GCE n1-standard-2 机器类型
- 7.5 GB 内存
- 2 个 CPU
内存中索引内存使用量
本测试仅针对内存索引的内存使用情况进行基准测试。目标是查找上述 c1 和 c2,并了解存储系统的内存消耗上限。
我们通过 Go 运行时的 ReadMemStats 计算内存使用量。通过对比创建索引前后的已分配字节数差异来估算内存使用情况。该方法无法完全反映内存中索引本身的内存使用量,但可展示大致的消耗趋势。
| N | 版本数 | 键大小 | 内存占用 |
|---|---|---|---|
| 100K | 1 | 64 字节 | 22 MB |
| 100K | 5 | 64 字节 | 39 MB |
| 1M | 1 | 64 字节 | 218 MB |
| 1M | 5 | 64 字节 | 432 MB |
| 100K | 1 | 256 字节 | 41 MB |
| 100K | 5 | 256 字节 | 65 MB |
| 1M | 1 | 256 字节 | 409 MB |
| 1M | 5 | 256 字节 | 506 MB |
根据结果,我们可以计算 c1=120bytes、c2=30bytes。仅需两组数据即可计算 c1 和 c2,因为它们是公式中唯一的未知变量。c1=120bytes 和 c2=30bytes 是我们计算出的 4 组 c1 和 c2 的平均值。对于小键值对,键元数据开销仍相对显著(50%)。然而,这相较于旧存储系统已实现显著改进,后者至少存在 1000% 的开销。
整体内存使用情况
整体内存使用量反映了 etcd 在存储系统上的 RSS 内存占用情况。值的大小对 etcd 的整体内存使用量影响极小,因为值数据存储在磁盘上,仅将热值保留在内存中,由操作系统的页面缓存进行管理。
| N | versions | 键大小 | 值大小 | 内存占用 |
|---|---|---|---|---|
| 100K | 1 | 64 字节 | 256 字节 | 40 MB |
| 100K | 5 | 64 字节 | 256 字节 | 89 MB |
| 1M | 1 | 64 字节 | 256 字节 | 470 MB |
| 1M | 5 | 64 字节 | 256 字节 | 880 MB |
| 100K | 1 | 64 字节 | 1 KB | 102 MB |
| 100K | 5 | 64 字节 | 1 KB | 164 MB |
| 1M | 1 | 64 字节 | 1 KB | 587 MB |
| 1M | 5 | 64 字节 | 1 KB | 836 MB |
根据结果可知,值的大小对内存消耗的影响并不显著。由于操作系统页缓存中存储了更多数据,存在轻微的内存增长。
2 - 监听内存使用量基准测试
监听功能正处于积极开发中,其内存使用量可能随开发进展而变化。我们预计其内存使用量不会显著超过以下所述数值。
etcd 的一个核心目标是支持大量客户端执行海量监听操作。etcd 旨在支持 O(10k) 个客户端、O(100K) 个监听流(每个客户端约 O(10) 个监听流)以及 O(10M) 个总监听操作(每个监听流约 O(100) 个监听)。每个单独监听操作所消耗的内存占 etcd 整体内存使用量的最大部分,因此成为当前及未来优化的重点。
etcd 监听功能的三个相关组件会占用物理内存:每个 grpc.Conn、每个监听流以及每次监听活动的实例。grpc.Conn 维护实际的 TCP 连接及其他 gRPC 连接状态。每个 grpc.Conn 消耗约 10 KB 内存,且可能关联多个监听流。
每个监听流都是一个独立的 HTTP2 连接,消耗额外约 10 kB 的内存。 多个监听操作可能共享一个监听流。
监听是实际用于跟踪键值存储变更的结构。每个监听操作的内存消耗应低于 < 1 KB。
监听的理论内存消耗可通过以下公式近似计算:memory = c1 * number_of_conn + c2 * avg_number_of_stream_per_conn + c3 * avg_number_of_watch_stream
测试环境
etcd 版本
GCE n1-standard-2 机器类型
- 7.5 GB 内存
- 2 个 CPU
整体内存使用情况
总体内存使用量反映了 etcd 在客户端监听器存在的情况下所消耗的 RSS 。尽管结果可能有高达 10% 的波动,但该数据仍具有意义,因为目标是了解内存使用的粗略情况及分配模式。
根据基准测试结果,我们可以粗略计算出 c1 = 17kb、c2 = 18kb 和 c3 = 350bytes。因此,每个额外的客户端连接消耗 17 KB 内存,每个额外的流消耗 18 KB 内存,而每个额外的监听仅消耗 350 字节。在正常情况下,单个 etcd 服务器可使用几 GB 内存维持数百万个监听。
| 客户端数量 | 每客户端流数量 | 每流监听数量 | 总监听数量 | 内存占用 |
|---|---|---|---|---|
| 1k | 1 | 1 | 1k | 50MB |
| 2k | 1 | 1 | 2k | 90MB |
| 5k | 1 | 1 | 5k | 200MB |
| 1k | 10 | 1 | 10k | 217MB |
| 2k | 10 | 1 | 20k | 417MB |
| 5k | 10 | 1 | 50k | 980MB |
| 1k | 50 | 1 | 50k | 1001MB |
| 2k | 50 | 1 | 100k | 1960MB |
| 5k | 50 | 1 | 250k | 4700MB |
| 1k | 50 | 10 | 500k | 1171MB |
| 2k | 50 | 10 | 1M | 2371MB |
| 5k | 50 | 10 | 2.5M | 5710MB |
| 1k | 50 | 100 | 5M | 2380MB |
| 2k | 50 | 100 | 10M | 4672MB |
| 5k | 50 | 100 | 25M | OOM |
3 - etcd v3 基准测试
物理机
GCE n1-highcpu-2 机器类型
- 1x 专用本地 SSD,挂载于 /var/lib/etcd
- 1x 专用慢速磁盘,用于操作系统
- 1.8 GB 内存
- 2x CPU
- etcd 版本 2.2.0
etcd 集群
1 以 v3 演示模式运行的 etcd 成员
测试
使用 etcd v3 基准测试工具 。
性能
读取单一键
| 键大小(字节) | 客户端数量 | 读取 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|
| 256 | 1 | 2716 | 0.4 |
| 256 | 64 | 16623 | 6.1 |
| 256 | 256 | 16622 | 21.7 |
性能几乎与空服务器处理器的情况相同。
读取单个键的操作
| 键大小(字节) | 客户端数量 | 读取 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|
| 256 | 1 | 2269 | 0.5 |
| 256 | 64 | 13582 | 8.6 |
| 256 | 256 | 13262 | 47.5 |
空服务器处理器的性能不受单次写入操作影响。因此,性能下降应由存储系统导致。
4 - etcd v2.2.0-rc 内存基准测试
物理机
GCE n1-standard-2 机器类型
- 1 个专用本地 SSD,挂载于 /var/lib/etcd
- 1 个专用慢速磁盘,用于操作系统
- 7.5 GB 内存
- 2 个 CPU
etcd
测试
启动一个由 3 个成员组成的 etcd 集群,每个成员使用 2 个核心。
键名的长度始终为 64 字节,这是一个平均键字节数的合理长度。
内存最大使用量
- 当一个跟随者失效而领导者持续发送快照时,etcd 可能会使用最大内存。
max RSS是在三次运行中记录的最大内存使用量。
| 键字节数 | 键数量 | 数据大小(MB) | 最大 RSS(MB) | 领导者最大 RSS/数据比 |
|---|---|---|---|---|
| 128 | 50000 | 6 | 433 | 72x |
| 128 | 100000 | 12 | 659 | 54x |
| 128 | 200000 | 24 | 1466 | 61x |
| 1024 | 50000 | 48 | 1253 | 26x |
| 1024 | 100000 | 96 | 2344 | 24x |
| 1024 | 200000 | 192 | 4361 | 22x |
数据大小阈值
- 当 etcd 达到数据大小阈值时,可能容易触发选举,并丢弃部分提案。
- 对于大多数情况,只要 etcd 集群未触及该阈值,即可正常运行。若因资源不足导致运行不佳,应减小其数据规模。
| 键大小(字节) | 键数量限制 | 建议数据大小阈值(MB) | 消耗的 RSS(MB) |
|---|---|---|---|
| 128 | 400K | 48 | 2400 |
| 1024 | 300K | 292 | 6500 |
5 - etcd v2.2.0-rc 基准测试
物理机
GCE n1-highcpu-2 机器类型
- 1 个专用本地 SSD,挂载于 /var/lib/etcd
- 1 个专用慢速磁盘,用于操作系统
- 1.8 GB 内存
- 2 个 CPU
etcd 集群
3 etcd 2.2.0-rc 成员,每个成员运行在单台机器上。
详细版本:
此外,我们使用 3 个 etcd 2.1.0 alpha 阶段成员组成集群以获取基准性能。etcd 的提交头位于 c7146bd5 ,与 etcd 2.1 基准测试 中所用版本相同。
测试
引导另一台机器,并使用 hey HTTP 压力测试工具 向每个 etcd 成员发送请求。请参阅 基准测试黑客指南 以获取详细操作说明。
性能
读取单一键
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 读取 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 2804 (-5%) | 0.4 (+0%) |
| 64 | 64 | 仅领导者 | 17816 (+0%) | 5.7 (-6%) |
| 64 | 256 | 仅领导者 | 18667 (-6%) | 20.4 (+2%) |
| 256 | 1 | 仅领导者 | 2181 (-15%) | 0.5 (+25%) |
| 256 | 64 | 仅领导者 | 17435 (-7%) | 6.0 (+9%) |
| 256 | 256 | 仅领导者 | 18180 (-8%) | 21.3 (+3%) |
| 64 | 64 | 所有服务器 | 46965 (-4%) | 2.1 (+0%) |
| 64 | 256 | 所有服务器 | 55286 (-6%) | 7.4 (+6%) |
| 256 | 64 | 所有服务器 | 46603 (-6%) | 2.1 (+5%) |
| 256 | 256 | 所有服务器 | 55291 (-6%) | 7.3 (+4%) |
编写一个键
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 写入 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 76(+22%) | 19.4(-15%) |
| 64 | 64 | 仅领导者 | 2461(+45%) | 31.8(-32%) |
| 64 | 256 | 仅领导者 | 4275(+1%) | 69.6(-10%) |
| 256 | 1 | 仅领导者 | 64(+20%) | 16.7(-30%) |
| 256 | 64 | 仅领导者 | 2385(+30%) | 31.5(-19%) |
| 256 | 256 | 仅领导者 | 4353(-3%) | 74.0(+9%) |
| 64 | 64 | 所有服务器 | 2005(+81%) | 49.8(-55%) |
| 64 | 256 | 所有服务器 | 4868(+35%) | 81.5(-40%) |
| 256 | 64 | 所有服务器 | 1925(+72%) | 47.7(-59%) |
| 256 | 256 | 所有服务器 | 4975(+36%) | 70.3(-36%) |
性能变化说明
在大多数场景下,读取 QPS 下降了 5%~8%。原因是 etcd 会为每次存储操作记录存储指标。这些指标对监控和调试至关重要,因此该情况可接受。
写入 QPS 到领导者提升了 20%~30%。这是因为我们将 Raft 主循环与条目应用循环解耦,避免了两者相互阻塞。
所有服务器的写入 QPS 提升了 30% 至 80%,因为跟随者可更早接收到最新的提交索引,从而更快地提交提案。
6 - etcd v2.2.0 基准测试
物理机
GCE n1-highcpu-2 机器类型
- 1 块专用本地 SSD,挂载为 etcd 数据目录
- 1 块专用慢速磁盘,用于操作系统
- 1.8 GB 内存
- 2 个 CPU
etcd 集群
3 etcd 2.2.0 成员,每个成员运行在单台机器上。
详细版本:
测试
在 etcd 集群外部引导另一台机器,并运行 hey HTTP 基准测试工具
(含连接复用补丁),向每个 etcd 集群成员发送请求。请参阅 基准测试说明
获取补丁及复现我们操作步骤的详细信息。
性能通过 100 次基准测试结果计算得出。
性能
单键读取性能
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 平均读取 QPS | 读取 QPS 标准差 | 平均 90th 百分位延迟(毫秒) | 延迟标准差 |
|---|---|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 2303 | 200 | 0.49 | 0.06 |
| 64 | 64 | 仅领导者 | 15048 | 685 | 7.60 | 0.46 |
| 64 | 256 | 仅领导者 | 14508 | 434 | 29.76 | 1.05 |
| 256 | 1 | 仅领导者 | 2162 | 214 | 0.52 | 0.06 |
| 256 | 64 | 仅领导者 | 14789 | 792 | 7.69 | 0.48 |
| 256 | 256 | 仅领导者 | 14424 | 512 | 29.92 | 1.42 |
| 64 | 64 | 所有服务器 | 45752 | 2048 | 2.47 | 0.14 |
| 64 | 256 | 所有服务器 | 46592 | 1273 | 10.14 | 0.59 |
| 256 | 64 | 所有服务器 | 45332 | 1847 | 2.48 | 0.12 |
| 256 | 256 | 所有服务器 | 46485 | 1340 | 10.18 | 0.74 |
单键写入性能
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 平均写入 QPS | 写入 QPS 标准差 | 平均 90th 百分位延迟(毫秒) | 延迟标准差 |
|---|---|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 55 | 4 | 24.51 | 13.26 |
| 64 | 64 | 仅领导者 | 2139 | 125 | 35.23 | 3.40 |
| 64 | 256 | 仅领导者 | 4581 | 581 | 70.53 | 10.22 |
| 256 | 1 | 仅领导者 | 56 | 4 | 22.37 | 4.33 |
| 256 | 64 | 仅领导者 | 2052 | 151 | 36.83 | 4.20 |
| 256 | 256 | 仅领导者 | 4442 | 560 | 71.59 | 10.03 |
| 64 | 64 | 所有服务器 | 1625 | 85 | 58.51 | 5.14 |
| 64 | 256 | 所有服务器 | 4461 | 298 | 89.47 | 36.48 |
| 256 | 64 | 所有服务器 | 1599 | 94 | 60.11 | 6.43 |
| 256 | 256 | 所有服务器 | 4315 | 193 | 88.98 | 7.01 |
性能变化
由于 etcd 现在会记录每个 API 调用的指标,大多数场景下读取 QPS 性能似乎出现轻微下降。这种极小的性能影响被认为是对所返回监控与调试信息广度的合理投入。
写入 QPS 到集群领导者似乎略有增加。这是因为 etcd Raft 逻辑中主循环与条目应用循环已解耦,消除了两者之间的多个阻塞点。
写入 QPS 向所有成员显著增加,因为跟随者现在能更早接收到最新的提交索引,从而更快地提交提案。
7 - etcd v2.1.0 基准测试
物理机
GCE n1-highcpu-2 机器类型
- 1 块专用本地 SSD,挂载于 /var/lib/etcd
- 1 块专用慢速磁盘,用于操作系统
- 1.8 GB 内存
- 2 个 CPU
- etcd 版本 2.1.0 alpha
etcd 集群
3 个 etcd 成员,每个成员运行在单台机器上
测试
引导另一台机器,并使用 hey HTTP 压力测试工具 向每个 etcd 成员发送请求。请参阅 基准测试黑客指南 以获取详细操作说明。
性能
读取单一键
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 读取 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 1534 | 0.7 |
| 64 | 64 | 仅领导者 | 10125 | 9.1 |
| 64 | 256 | 仅领导者 | 13892 | 27.1 |
| 256 | 1 | 仅领导者 | 1530 | 0.8 |
| 256 | 64 | 仅领导者 | 10106 | 10.1 |
| 256 | 256 | 仅领导者 | 14667 | 27.0 |
| 64 | 64 | 所有服务器 | 24200 | 3.9 |
| 64 | 256 | 所有服务器 | 33300 | 11.8 |
| 256 | 64 | 所有服务器 | 24800 | 3.9 |
| 256 | 256 | 所有服务器 | 33000 | 11.5 |
编写一个键
| 键大小(字节) | 客户端数量 | 目标 etcd 服务器 | 写入 QPS | 第 90 百分位延迟(毫秒) |
|---|---|---|---|---|
| 64 | 1 | 仅领导者 | 60 | 21.4 |
| 64 | 64 | 仅领导者 | 1742 | 46.8 |
| 64 | 256 | 仅领导者 | 3982 | 90.5 |
| 256 | 1 | 仅领导者 | 58 | 20.3 |
| 256 | 64 | 仅领导者 | 1770 | 47.8 |
| 256 | 256 | 仅领导者 | 4157 | 105.3 |
| 64 | 64 | 所有服务器 | 1028 | 123.4 |
| 64 | 256 | 所有服务器 | 3260 | 123.8 |
| 256 | 64 | 所有服务器 | 1033 | 121.5 |
| 256 | 256 | 所有服务器 | 3061 | 119.3 |