调优

何时更新心跳间隔和选举超时设置

在本地网络中部署 etcd 时,如果平均网络延迟较低,则其默认设置通常可以良好运行。然而,当 etcd 跨多个数据中心使用,或在网络延迟较高的环境中运行时,可能需要调整心跳间隔和选举超时设置。

网络并不是延迟的唯一来源。每个请求和响应都可能受到领导者和跟随者节点上磁盘速度慢的影响。这些超时值代表了从发出请求到另一台机器成功响应之间的总耗时。

时间参数

底层的分布式共识协议依赖两个独立的时间参数,以确保当某个节点停滞或离线时,其他节点能够接管领导权。第一个参数称为心跳间隔(Heartbeat Interval),即领导者通知其跟随者自己仍处于活跃状态的频率。最佳实践建议将该参数设置为节点间往返时间(RTT)的水平。默认情况下,etcd 使用 100ms 的心跳间隔。

第二个参数是选举超时(Election Timeout)。这是指一个跟随者在未收到心跳信号后,等待多长时间便尝试成为新的领导者。默认情况下,etcd 使用 1000ms 的选举超时。

调整这两个参数需要权衡利弊。心跳间隔的推荐值应接近成员之间的平均往返时间(RTT),通常为 RTT 的 0.5 到 1.5 倍。如果心跳间隔过低,etcd 将发送不必要的消息,增加 CPU 和网络资源的消耗;反之,若心跳间隔过高,则会导致选举超时时间变长,从而延长检测领导者故障所需的时间。测量往返时间(RTT)最简单的方法是使用PING 工具

选举超时应根据心跳间隔和成员间的平均往返时间来设置。选举超时必须至少是往返时间的 10 倍,以便应对网络波动。例如,如果成员之间的往返时间为 10ms,则选举超时应至少设置为 100ms。

选举超时的上限为 50000ms(即 50 秒),仅应在部署全球分布式的 etcd 集群时使用。在美国大陆范围内,合理的往返时间约为 130ms,而美国与日本之间的往返时间约为 350-400ms。如果网络性能不稳定或经常出现数据包延迟或丢失,则可能需要多次重试才能成功发送数据包。因此,5 秒可视为全球范围内的安全往返时间上限。由于选举超时应比广播时间大一个数量级,在全球分布式集群中往返时间约为 5 秒的情况下,50 秒成为一个合理的最大值。

在一个集群中的所有成员上,心跳间隔和选举超时的值应当保持一致。为不同 etcd 成员设置不同的值可能会破坏集群的稳定性。

可以通过命令行覆盖默认值:

# Command line arguments:
$ etcd --heartbeat-interval=100 --election-timeout=500

# Environment variables:
$ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd

这些值以毫秒为单位指定。

快照

etcd 会将所有的键更改追加写入一个日志文件。这个日志会无限增长,并完整记录每一个对键所做的修改。对于负载较轻的集群来说,保留完整的变更历史是可行的;但对于高负载的集群,这会导致日志文件变得非常庞大。

为了避免日志过大,etcd 会定期创建快照。这些快照通过保存系统的当前状态并删除旧的日志,实现对日志的压缩。

快照调优

使用 V2 后端创建快照可能开销较大,因此只有在对 etcd 进行一定数量的更改后才会创建快照。默认情况下,每进行 10,000 次更改后会创建一次快照。如果 etcd 的内存和磁盘使用率过高,可以尝试通过在命令行中设置以下参数来降低快照阈值:

# Command line arguments:
$ etcd --snapshot-count=5000

# Environment variables:
$ ETCD_SNAPSHOT_COUNT=5000 etcd

磁盘

etcd 集群对磁盘延迟非常敏感。由于 etcd 必须将其提案持久化到日志中,其他进程产生的磁盘活动可能导致较长的 fsync 延迟。其结果是 etcd 可能错过心跳,导致请求超时和临时失去领导者角色。若给予 etcd 较高的磁盘优先级,有时可使其与其他进程稳定共存。

在 Linux 系统上,可以使用 ionice 配置 etcd 的磁盘优先级:

# best effort, highest priority
$ sudo ionice -c2 -n0 -p `pgrep etcd`

网络

如果 etcd 领导者处理大量并发客户端请求,可能会因网络拥塞而延迟处理从属节点的请求。这会在从属节点上表现为发送缓冲区错误消息:

dropped MsgProp to 247ae21ff9436b2d since streamMsg's sending buffer is full
dropped MsgAppResp to 247ae21ff9436b2d since streamMsg's sending buffer is full

这些问题可以通过优先处理 etcd 的节点间通信流量而非客户端流量来解决。在 Linux 上,可以使用流量控制机制(traffic control)来提升节点间流量的优先级:

tc qdisc add dev eth0 root handle 1: prio bands 3
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1

要取消 tc 设置,请执行:

tc qdisc del dev eth0 root

CPU

由于 etcd 对延迟非常敏感,可以在 Linux 系统上将 CPU 调节器设置为 performance(性能)或 conservative(保守)模式,以进一步优化性能。

在 Linux 上,可将 CPU 调节器配置为 performance 模式:

echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

最后更新于 2025 年 6 月 3 日:递归地将 v3.6 的内容复制到 v3.7(a90b2a6)