etcd 与分布式键值

共 19 题
📑 题目列表 19 题
#
★★★

1. etcd 的 Raft 一致性协议与 MVCC 多版本

请解释 etcd 的 Raft 一致性协议如何工作,以及 MVCC(多版本并发控制)机制如何实现键值历史版本管理?

  • Raft 的 Leader 选举与日志复制
  • 线性读写与 Raft
  • MVCC 的 revision 与历史版本

etcd 使用 Raft 协议实现分布式一致性。Raft 将节点分为 Leader、Follower、Candidate,Leader 负责接收写请求并复制日志到 Follower,日志获得多数派确认后提交;Leader 通过心跳维持地位,Leader 故障时通过选举时间戳(election timeout)触发新选举。MVCC 是 etcd 的多版本机制:每个键值操作都产生一个全局递增的 revision(版本号),每次修改键时并不覆盖旧值,而是保留旧版本,通过 (key, revision) 三元组记录历史。客户端可用指定 revision 读取历史数据,或使用 version 计数当前值的修改次数。MVCC 与 Watch 紧密结合:Watch 依靠 revision 进行增量观察,客户端记录 last revision,后续只推送该 revision 之后的变化。

Raft 提供了"日志一致 + 线性一致"的基石,MVCC 在一致存储之上提供了历史版本与增量监听能力,这使 etcd 天然适合做配置中心、服务发现和协调原语。MVCC 的根是 revision 全局单调递增,所有读写和 Watch 都以此为准。

#
★★★

2. etcd 的分布式锁(txn + lease)实现

请说明如何利用 etcd 的事务(txn)与租约(lease)实现一个健壮的分布式锁,包括加锁、续期、解锁与故障释放?

  • txn 的原子比较(CompareAndSwap)
  • lease 租约与自动过期
  • 锁的续期(KeepAlive)

etcd 分布式锁的经典实现:首先创建带 TTL 的 lease 租约,然后用 txn 事务原子地尝试在锁 key 上写入持有者信息(如客户端 ID),并设置 lease 关联。事务中通过 Compare(create_revision 或 version 比较)判断锁 key 是否已被占用:若未被占用(Compare 成功)则写入并加锁;若已被占用(Compare 失败)则加锁失败,可读取当前持有者并 Watch 该 key 等待释放。加锁成功后,通过 KeepAlive 周期续期租约,防止锁因 TTL 到期早期释放。解锁时删除锁 key 并撤销租约。若客户端崩溃,lease 因无 KeepAlive 而 TTL 到期,etcd 自动删除锁 key 释放锁,无需人工干预。etcd 官方 client 提供的 concurrency 包(NewMutex)正是基于 txn+lease 实现。

txn 保证"检查与写入"原子进行,杜绝竞态;lease 提供"崩溃自动释放"的兜底,避免死锁;KeepAlive 防止正常运行中被误释放。相比 Redis 锁,etcd 锁的强一致性和 lease 语义更可靠,常用于选主和关键资源的互斥。

#
★★★

3. etcd 与 ZooKeeper 的性能与适用场景差异

请对比 etcd 与 ZooKeeper 在性能特性、接口设计、一致性与适用场景上的差异,说明各自适合的场景?

  • 一致性协议(Raft vs ZAB)
  • 写性能与读性能
  • 适用场景与生态

一致性上两者都是 CP,但 etcd 用 Raft、ZK 用 ZAB。接口上 etcd 用 gRPC + protobuf,支持 Watch 流式推送、前缀监听、MVCC 历史版本;ZK 用自定义 Java 协议,Watch 一次性需重注册。性能上 etcd 的读(配合 LeaseRead 等)和多版本 Watch 更高效,配套的 Batch 写和并发写优化使其在 K8s 场景下表现良好;ZK 的写受 Leader 串行 + 刷盘限制,读在 Follower 上可扩展但可能读到旧值。Watch 语义上 etcd 是长连接流式推送(可恢复、自带从某 revision 续传),ZK 是一次性事件需手动重注册,易丢事件。适用场景:etcd 适合云原生(Kubernetes 元数据)、配置中心、服务发现、协调;ZK 适合 Kafka/HBase 等传统大数据生态的协调与元数据。

差异本质是"现代 vs 经典":etcd 的 API 更现代、Watch 更可靠、运维更简单,ZK 更成熟但接口陈旧。选型时看生态绑定(Kafka 需要 ZK)与团队熟悉度,新项目优先考虑 etcd。

#
★★★

4. etcd 的 MVCC 版本管理(key revision/mod_revision)与业务层乐观并发控制

请解释 etcd 的 MVCC 版本管理机制,包括 key 的 revision、mod_revision、create_revision 等字段,以及如何利用这些字段在业务层实现乐观并发控制?

  • revision/create_revision/mod_revision/version 字段
  • MVCC 的历史版本读取
  • 基于 mod_revision 的乐观锁

etcd 中每个键关联多个版本字段:revision(全局每次修改递增的总版本号)、create_revision(键创建时的全局 revision)、mod_revision(键最后一次被修改的全局 revision)、version(键自身被修改的次数)。MVCC 保留键的历史版本,客户端可以用指定 revision 读取历史数据。业务层乐观并发控制利用 txn 的 Compare 操作:例如 Compare(mod_revision, "=", expectedRev) 判断键的修改版本是否与预期一致,一致才执行 Update 写入,否则事务失败。这样实现"读-判断-写"的原子 CAS,避免并发覆盖。也可用 mod_revision 作为乐观锁的版本号,冲突时重试。

mod_revision 是全局递增的,天然适合作为乐观锁版本号;txn 的 Compare 保证版本判断与写入原子执行。业务层只需维护"读到的 mod_revision",在写入时带上 Compare 即可实现无锁的乐观并发控制。

#
★★★

5. etcd 的 Raft 实现,MVCC、Watch 机制与租约(Lease)如何设计?

请说明 etcd 的 Raft 实现中,MVCC、Watch 机制与租约(Lease)三大组件是如何协同设计的?

  • Raft 与 MVCC 的版本关联
  • Watch 基于 revision 的增量推送
  • Lease 与心跳、TTL、KeepAlive

etcd 的架构中,Raft 负责日志复制与共识,MVCC 在 Raft 提交的日志之上构建键值存储并维护全局 revision。每次 Raft 提交一个含键值变更的事务,MVCC 就分配一个对应的 revision 并写入变更记录,同时触发 Watch 通知。Watch 组件基于 revision 实现增量监听:客户端从某个 revision 开始订阅,etcd 在后台把该 revision 之后的所有变更推送给客户端,支持前缀和范围监听,且断线后可从上次的 revision 续传。租约(Lease)是独立的 TTL 机制:客户端创建 lease 并关联键,通过 KeepAlive 续期,lease 过期时 etcd 自动删除关联的键并触发 Watch。三者协同:Raft 保证一致性,MVCC 提供版本与历史,Watch 提供实时通知,Lease 提供"TTL + 自动清理"语义,共同支撑分布式锁、选主、配置中心等协调能力。

MVCC 的 revision 是连接 Raft、Watch、Lease 的枢纽:Raft 提交→分配 revision→MVCC 落库→Watch 推送,Lease 过期也走 MVCC 的删除路径并触发 Watch。这套设计让 etcd 成为 K8s 与协调场景的坚实基础。

#
★★

6. etcd 在 Kubernetes 中作为元数据存储的角色

请说明 etcd 在 Kubernetes 中作为核心元数据存储的角色,以及 K8s 对 etcd 的使用方式与可靠性要求?

  • etcd 存储 K8s 集群状态
  • watch 机制与 API 监听
  • 高可用要求

Kubernetes 使用 etcd 作为唯一的核心元数据存储,存储集群的所有状态:Pod、Service、Deployment、ConfigMap、Node 等 API 对象,以及集群的配置与状态。K8s 的 API Server 通过 etcd 的 gRPC 接口读写,并通过 watch 流式监听实现控制器(Controller)的声明式协调——当资源变化时通过 watch 通知控制器收敛。因此 etcd 是 K8s 的"大脑",其可用性直接决定集群可用性。etcd 需以高可用集群(通常 3 或 5 节点)部署,开启 TLS 认证,并定期备份快照(snapshot),支持灾备恢复。etcd 的读性能、磁盘 IO 和空间是 K8s 集群扩展的关键瓶颈。

K8s 的设计高度依赖 etcd 的强一致与 watch 能力:声明式 API + 控制器模式需要可靠的实时状态同步。etcd 故障会导致 K8s 无法读写集群状态,因此其高可用、备份与性能调优是 K8s 运维的核心。

#
★★

7. etcd 的 lease(租约)与 key 自动过期机制

请说明 etcd 的 lease(租约)机制如何实现 key 的自动过期,以及 lease 的创建、绑定、续期和撤销流程?

  • lease 的 TTL 与租约对象
  • 键与 lease 的绑定
  • KeepAlive 续期

etcd 的 lease 是一个带 TTL(生存时间)的租约对象。客户端创建 lease 后,可将多个 key 关联(绑定)到该 lease 上。客户端通过 KeepAlive 周期性续期,使 lease 的剩余时间不断刷新。如果客户端停止 KeepAlive(如崩溃或主动撤销),lease 在 TTL 到期后过期,etcd 会自动删除所有关联到该 lease 的 key,并触发相应的 Watch 通知。客户端也可主动 Revoke 撤销 lease,立即删除关联的 key。lease 的典型应用是分布式锁(崩溃自动释放)、服务注册(实例心跳在线)和临时配置。可以通过 Grant 设置 TTL,LeaseKeepAlive 续期,LeaseRevoke 撤销。

lease 将"分布式对象生命周期"与"客户端活性"解耦:TTL 是兜底,KeepAlive 是活性证明,两者结合实现"客户端失联自动清理"的语义。相比 ZK 的临时节点(会话绑定),etcd 的 lease 更灵活,可将任意 key 绑定到租约。

#
★★

8. etcd 的 watch 流式监听与前缀监听

请说明 etcd 的 watch 流式监听与前缀监听机制,以及它们在工程中的应用场景?

  • 流式 Watch 长连接
  • 前缀监听与范围监听
  • 从指定 revision 续传

etcd 的 watch 是长连接流式推送:客户端通过 gRPC 建立一个 Watch 会话,etcd 持续把键的变更事件推送给客户端,无需反复注册。Watch 支持前缀监听(WatchPrefix)和范围监听(WatchRange),可以对某前缀下的所有键(如 /services/ 下的所有服务实例)进行实时监听,这是配置中心、服务发现、控制器协调的关键能力。Watch 还支持指定 start revision 从历史某个版本开始监听,断线后可从上次记录的 revision 续传,避免丢失事件。相比一次性 Watch,etcd 的流式 watch 更可靠、更高效,且能处理历史回溯。

前缀监听让客户端用一次 Watch 覆盖一组相关键,配合"从 revision 续传"实现不丢事件的可靠增量同步,这是 etcd 相较 ZK 在 Watch 上的核心优势,也是 K8s 控制器和 Nacos 类配置中心的底层基础。

#
★★

9. etcd 的 compact 与历史版本清理

请说明 etcd 的 compact(压缩)机制如何清理历史版本数据,以及它的必要性与工程配置?

  • MVCC 历史版本的堆积
  • compact 回收历史版本
  • 保留 revision 的策略

etcd 的 MVCC 会保留每个键的历史版本,如果不清理,历史版本会持续累积导致存储空间膨胀和性能下降。compact 机制用于删除指定 revision 之前的所有历史版本数据,只保留 revision 之后的数据。客户端通过 Compact(revision) 提交压缩请求,etcd 会删除该 revision 之前的所有旧版本,使这些历史不可再读取。压缩后,Watch 的起始 revision 如果早于压缩的 revision 会报错(Compacted 错误),因此客户端需记录并及时续传。compact 是"逻辑删除历史版本",不立即释放磁盘空间,磁盘空间的释放需要配合 defrag(碎片整理)重新整理。工程上应定期 compact(如每天/每小时),并保留合理窗口的历史版本供回溯。

compact 是 etcd 存储卫生的关键:不压缩则历史无限增长,压缩过头则丢失历史回溯能力与 Watch 断线续传。合理的策略是"定时 compact + 保留最近 N 个 revision 窗口 + 定期 defrag 释放磁盘"。

#
★★

10. etcd 的租约与 KeepAlive,分布式锁与领导选举如何依赖租约续期?

请说明 etcd 的租约与 KeepAlive 续期机制如何支撑分布式锁和领导选举,以及续期失败时系统的行为?

  • 租约绑定锁/选举 key
  • KeepAlive 续期维持持有
  • 续期失败导致自动释放

在分布式锁和领导选举中,客户端创建带 TTL 的 lease 并将锁 key 绑定到 lease 上,通过 KeepAlive 周期续期。只要客户端健康并持续续期,lease 就一直有效,锁/Leader 身份得以维持;一旦客户端故障或网络中断,KeepAlive 停止,lease 在 TTL 到期后过期,etcd 自动删除关联的锁/选举 key,触发 Watch 通知其他等待者,从而完成锁的自动释放和 Leader 的自动让位。这个机制与 ZK 的会话超时+临时节点异曲同工:KeepAlive 对应心跳,TTL 对应会话超时,lease 关联 key 对应临时节点。续期失败时,客户端恢复后应重新竞选(重新加锁),不能假设锁仍在自己手里。

lease+KeepAlive 提供了"活性证明"与"自动释放"双重保障,是分布式锁/选举可靠性的核心。客户端必须持续续期,且要处理续期失败(可能已丢锁)的情况,重新参与竞争。

#
★★

11. etcd 的存储配额(quota)与告警(alarm)、碎片整理(defrag)的运维

请说明 etcd 的存储配额(quota)、告警(alarm)和碎片整理(defrag)机制,以及它们在 etcd 运维中的作用?

  • 存储配额与 NOSPACE 告警
  • 空间不足时的处理
  • defrag 碎片整理

etcd 默认设置存储配额(默认 2GB),当数据库大小达到配额时,etcd 会触发 NOSPACE 告警并发起只读保护,拒绝新的写入以保护集群。运维需先通过 compact 清理历史版本、释放逻辑空间,再 defrag 重组存储释放物理磁盘空间,最后清除告警(alarm disarm)恢复写入。defrag(碎片整理)用于回收 MVCC compact 后留下的碎片空间,它通过重新整理 boltdb 页面释放磁盘,但 defrag 需要逐节点进行且会短暂影响该节点性能。运维监控应关注"DB size vs quota"、告警状态、磁盘 IO 和碎片率,避免 quota 写满导致集群不可写。

quota+alarm+compact+defrag 构成 etcd 存储空间的完整运维闭环:quota 是保护上限,alarm 是报警信号,compact 回收逻辑空间,defrag 释放物理空间。不及时处理会因 NOSPACE 导致 etcd 拒写,进而影响 K8s 等上层系统。

#
★★

12. etcd 的 TLS 客户端认证与集群成员变更(learner)流程

请说明 etcd 的 TLS 客户端认证与集群成员变更(特别是 learner 成员)流程,以及成员变更的安全性?

  • TLS 双向认证与客户端证书
  • 成员变更(add/remove member)
  • learner 成员(只参与学习不参与投票)

etcd 支持 TLS 双向认证(mTLS):客户端与服务器之间互相验证证书,通过 CA 签发证书、Server、Peer、Client 证书,实现客户端身份认证与加密通信。生产环境(尤其 K8s)必须开启 TLS 防止中间人攻击和未授权访问。集群成员变更通过 member add/remove 接口进行,变更请求由 Raft 共识提交,保证成员列表的一致性。etcd 3.4+ 支持 learner 成员:新成员先以 learner 身份加入,只同步数据、参与验证但不参与投票、不参与选举,避免新成员追赶日志期间拖慢集群,待数据追平后通过 MemberPromote 提升为正式成员。这保证了成员变更过程中的集群稳定与安全。

learner 机制解决了"向集群添加新成员时因追赶日志导致拖慢 Raft"的问题,是 etcd 成员变更的工程优化。TLS 双向认证则是集群安全的基础,K8s 中 etcd 通讯默认强制 TLS。

#
★★

13. etcd 的 watch 与 MVCC,历史版本保留与压缩(compact)的工程配置如何?

请说明 etcd 的 watch 与 MVCC 如何配合历史版本保留与压缩(compact)机制,并给出工程配置建议?

  • watch 依赖 revision 继续
  • 历史版本保留策略
  • compact 的频率与窗口

etcd 的 watch 依赖 MVCC 的 revision 进行增量同步:客户端记录 last revision,断线后从该 revision 续传。但 MVCC 会定期 compact 删除旧版本,如果客户端记录的 revision 已被 compact 掉,续传会失败(Compacted 错误)。因此工程配置需要权衡:compact 太频繁会丢失长时间离线客户端的续传能力,太稀疏会导致历史版本堆积、存储膨胀。实践建议:根据历史版本保留需求设置 compact 窗口,例如保留最近 24 小时或最近 N 个 revision;客户端应持久化 last revision 并在 compact 后及时续传;监控存储增长,定期 defrag 释放磁盘;对重要历史可做快照(snapshot)备份。K8s 等场景通过定期 compact 和 defrag 保障 etcd 长期稳定。

历史版本保留与 compact 是一对矛盾:保留越多越利于回溯与续传,但存储成本越高。关键是把"保留窗口"与"客户端续传能力"对齐,配合定期 defrag 形成完整的存储生命周期管理。

#

14. etcd 的 gRPC 接口与 Java 客户端(jetcd)

请说明 etcd 的 gRPC 接口设计,以及 Java 客户端 jetcd 的使用方式与特性?

  • gRPC + protobuf 接口
  • jetcd 的 API(KV/Watch/Lease)
  • 集成与序列化

etcd 通过 gRPC 提供 RPC 接口,使用 protobuf 定义消息,主要服务包括 KV(读写执行 txn)、Watch(流式监听)、Lease(租约管理)、Cluster(成员管理)、Maintenance(维护)。gRPC 支持 HTTP/2、双向流、多路复用,天然适合流式 Watch 和长连接。jetcd 是 etcd 的官方 Java 客户端,提供 JetcdClient 封装 KV、Watch、Lease、Tx 等 API,支持异步(CompletableFuture)与流式 Watch 回调。使用 jetcd 时需引入依赖,配置 endpoints(多个 etcd 地址)与 TLS 证书,通过 KV 的 get/put/delete、Watch 的 watch 前缀、Lease 的 grant/keepAlive 实现分布式键值操作。可与 Spring Boot 集成,封装为 Bean 或使用相关 starter。

gRPC 的 HTTP/2 长连接与流式能力是 etcd 高性能 Watch 的基础,jetcd 把这些能力封装为 Java 友好的异步 API。相比 ZK 的自定义协议,etcd+gRPC 更标准化,跨语言互操作更好。

#

15. etcd vs ZooKeeper,一致性模型、接口(gRPC vs ZK API)与运维差异如何?

请对比 etcd 与 ZooKeeper 在一致性模型、接口形式和运维复杂度上的差异,并说明各自的取舍?

  • 一致性模型(Raft vs ZAB)
  • 接口(gRPC vs ZK 自定义协议)
  • 运维复杂度(命令、监控、部署)

一致性模型上,两者都是 CP 强一致,但实现不同:etcd 用 Raft,ZK 用 ZAB。接口上,etcd 用 gRPC + protobuf,支持流式 Watch、前缀监听、MVCC、txn;ZK 用自定义 Java 协议和树形 Znode API,Watch 一次性。运维上,etcd 部署更简单(单二进制、gRPC 端口、易于容器化),提供 v3 的 member/compact/defrag/snapshot 等命令,监控指标丰富;ZK 需要管理 4lw 命令、会话连接、多节点配置,运维相对繁琐。数据模型上,etcd 是扁平 KV+前缀,ZK 是树形 Znode。总体而言,etcd 更现代、更易运维、更适合云原生;ZK 更成熟、生态绑定(Kafka/HBase)更紧密。

差异的核心是"设计代际":etcd 面向云原生与 gRPC 生态,重 API 与可运维性;ZK 面向传统大数据生态,重成熟稳定。工程选型应结合周边生态与团队能力,不能只看单点能力。

#

16. etcd 的集群运维,快照备份、成员变更与数据恢复(灾备)如何?

请说明 etcd 集群的快照备份、成员变更与数据恢复(灾备)流程,以及如何保障数据安全?

  • snapshot 快照备份
  • 成员变更(add/remove/learner)
  • 从快照恢复数据

etcd 的备份通过 snapshot 命令生成一致性快照(etcdctl snapshot save),快照包含所有键值数据,可在任意时间点备份。成员变更通过 member add/remove 管理,新成员以 learner 加入再提升,避免影响集群。数据恢复场景:当集群多数节点故障或数据损坏时,可从最近快照恢复——用 snapshot 启动新节点,通过 member add 重建集群,或从备份恢复单节点数据。灾备最佳实践:定期(如每天)快照备份并异地存储,开启自动 snapshot 与压缩,监控 DB 大小与告警,恢复前先验证快照完整性,恢复时保持集群成员一致性。由于 etcd 是 K8s 等系统的核心,其快照与恢复能力直接决定集群的灾难恢复能力。

快照是 etcd 数据安全的底线,配合成员变更与恢复流程构成完整的灾备体系。恢复时要遵循"先备份、再重建、后验证"的顺序,避免数据丢失或集群状态不一致。

#

17. etcd 的存储引擎,boltdb/bbolt 的 B+tree 与 WAL 的持久化如何?

请说明 etcd 的存储引擎 boltdb/bbolt 的 B+tree 组织方式与 WAL(预写日志)持久化机制,以及它们如何保障数据可靠性与性能?

  • boltdb/bbolt 的 B+tree 存储
  • WAL 预写日志
  • 数据落盘与恢复

etcd 使用 bbolt(BoltDB 的社区维护增强版)作为存储引擎,bbolt 是单机嵌入式 KV 数据库,用 B+tree 组织数据以支持有序范围遍历和高效查询。bbolt 采用事务模型,写操作先写 WAL(预写日志)再落盘,通过顺序写日志保证持久性,崩溃时通过 WAL 重放恢复。etcd 的 MVCC 建立在 bbolt 之上:每个键的多个版本通过 B+tree 的版本桶组织,revision 作为索引,支持按 revision 范围查询。bbolt 的 mmap 映射与 B+tree 结构使 etcd 的读性能高、事务开销小。etcd 的 WAL 与 Raft 日志结合,Raft 日志先持久化再提交,保证一致性。

bbolt 的 B+tree 提供有序存储与范围查询(支撑前缀监听和 MVCC 的历史版本),WAL 提供崩溃恢复的持久性,两者结合为 etcd 的强一致与高性能存储奠定基础。Raft 日志与 bbolt 写入的配合是数据可靠性的关键。

#

18. etcd 的线性一致读,ReadIndex/LeaseRead 的实现差异如何?

请说明 etcd 的线性一致读(Linearizable Read)机制,以及 ReadIndex 与 LeaseRead 两种实现的差异与取舍?

  • 线性一致读的定义
  • ReadIndex 读
  • LeaseRead 读

线性一致读要求读操作返回集群中已提交的最新数据,保证读到的是与写一致的最新状态。etcd 默认(Raft 场景)的线性一致读有两种实现:ReadIndex 读和 LeaseRead 读。ReadIndex 读:Leader 记录当前 commit index,向多数节点确认(Heartbeat)后,等待该 commit index 被应用再返回读结果,保证读到的数据已提交。LeaseRead 读:Leader 利用自身 lease(基于 Raft 心跳的集群租约)在租约有效期内直接本地读,无需向多数节点确认,因为租约有效期内不会有其他 Leader 产生,读结果保证最新。差异:ReadIndex 需要一次网络往返确认,延迟较高但更鲁棒;LeaseRead 直接本地读,延迟低、性能高,但依赖时钟同步(租约假设),时钟偏移可能导致读到旧数据。生产环境通常用 ReadIndex 保证正确性,或用 LeaseRead 换性能。

线性一致读的本质是"确保读到集群已提交的最新状态"。ReadIndex 用"确认后读"保证正确性,LeaseRead 用"租约内直接读"换取性能,两者是正确性与性能的权衡,选择取决于对时钟与延迟的容忍度。

#

19. etcd 在分布式任务调度选主中的租约(lease)与 watch 组合

请说明 etcd 的租约(lease)与 watch 如何组合用于分布式任务调度的选主,以及选主后的任务协调机制?

  • 租约绑定选举 key
  • watch 监听选举结果
  • 主备切换与任务接管

在分布式任务调度中,通过 etcd 选主通常这样实现:每个候选节点创建带 lease 的选举 key,用 txn 原子写入自己的节点标识,成功者成为主节点;其余节点通过 watch 监听该 key,当主节点因故障(lease 到期)或主动释放而删除 key 时,watch 触发,其他节点重新竞选。主节点通过 KeepAlive 持续续期 lease 维持身份,并负责执行调度任务(如分发任务、管理任务状态)。从节点监听主节点状态,主节点失联后进行故障转移,接管任务。租约提供"崩溃自动让位",watch 提供"实时感知主节点变化",两者组合实现可靠的主备切换与任务接管。

lease 负责"活性与自动释放",watch 负责"状态感知与触发重新竞选",二者组合是 etcd 选主的完整方案。配合任务状态记录(如记录任务执行进度)可实现接力执行,避免重复执行。