第一模块:ETCD 基础概念与核心功能
1.1 什么是 ETCD?
ETCD 是一个开源的分布式键值存储系统(Key-Value Store),由 CoreOS 团队开发并捐赠给云原生计算基金会(CNCF)。它的设计目标是提供高可用性和强一致性的分布式数据管理服务,常用于分布式系统的配置管理、服务发现、分布式锁等场景。
核心特点:
简单性:基于 HTTP/JSON 或 gRPC 的 API 设计。
强一致性:使用 Raft 共识算法保证数据一致性。
高可用性:支持多节点集群部署,容忍部分节点故障。
持久化存储:数据默认持久化到磁盘,支持快照和恢复。
1.2 为什么需要 ETCD?
在分布式系统中,多个服务实例需要共享配置或协调状态。传统的关系型数据库难以满足高并发和低延迟的需求,而 ETCD 通过以下特性解决了这些问题:
低延迟读写:基于内存的键值存储,读写性能优异(每秒数万次操作)。
分布式协同:天然支持分布式场景下的数据同步。
与 Kubernetes 深度集成:Kubernetes 使用 ETCD 作为其默认的元数据存储组件。
示例场景: 假设有一个微服务集群,需要动态调整所有服务的日志级别。通过 ETCD 存储日志配置,服务实例监听 ETCD 中的配置变更,即可实现实时更新。
1.3 ETCD 的核心功能
键值存储(Key-Value Storage) ETCD 的核心功能是存储键值对,支持以下操作:
PUT:插入或更新键值。
GET:获取键值。
DELETE:删除键值。
WATCH:监听键值变化。
示例:通过 etcdctl 命令行工具操作键值:
# 写入键值
etcdctl put /config/app1/log_level "debug"
# 读取键值
etcdctl get /config/app1/log_level
# 输出:/config/app1/log_level debug
# 监听键值变化(另开一个终端执行)
etcdctl watch /config/app1/log_level
租约(Lease) 通过租约机制实现键值的自动过期。租约需要定期续期,否则绑定的键值会被自动删除。
示例:创建一个 10 秒的租约并绑定键值:
# 创建租约(返回 Lease ID)
etcdctl lease grant 10
# 输出:lease 12345abcd granted with TTL(10s)
# 将键值绑定到租约
etcdctl put --lease=12345abcd /temp/session "active"
事务(Transaction) 支持多操作的原子性提交,类似数据库事务。
示例:条件更新(只有键 /resource/lock 不存在时才写入):
etcdctl txn --interactive
# 输入以下内容:
compare:
mod("/resource/lock") = 0 # 检查键的修改版本是否为 0(不存在)
success requests: # 条件成立时执行的操作
put /resource/lock "owner1"
failure requests: # 条件不成立时执行的操作
get /resource/lock
1.4 快速入门:单节点部署与操作
步骤 1:安装 ETCD
从 ETCD GitHub Release 下载二进制文件(以 Linux 为例):
wget https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz
tar xzvf etcd-v3.5.0-linux-amd64.tar.gz
cd etcd-v3.5.0-linux-amd64
步骤 2:启动单节点 ETCD
./etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://localhost:2379
步骤 3:使用 etcdctl 测试
# 写入数据
./etcdctl put /test/key1 "Hello ETCD"
# 读取数据
./etcdctl get /test/key1
# 输出:/test/key1 Hello ETCD
# 监听数据变化(新终端执行)
./etcdctl watch /test/key1
1.5 实例:用代码操作 ETCD
以下是一个使用 Go 语言操作 ETCD 的简单示例:
package main
import (
"context"
"fmt"
"time"
"go.etcd.io/etcd/client/v3"
)
func main() {
// 创建客户端
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"http://localhost:2379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
panic(err)
}
defer cli.Close()
// 写入键值
ctx := context.Background()
_, err = cli.Put(ctx, "/config/app1/version", "1.0.0")
if err != nil {
panic(err)
}
// 读取键值
resp, err := cli.Get(ctx, "/config/app1/version")
if err != nil {
panic(err)
}
fmt.Printf("当前版本: %s\n", resp.Kvs[0].Value)
// 监听键值变化
watchChan := cli.Watch(ctx, "/config/app1/version")
for resp := range watchChan {
for _, ev := range resp.Events {
fmt.Printf("事件类型: %s, 新值: %s\n", ev.Type, ev.Kv.Value)
}
}
}
第二模块:ETCD 集群架构与高可用性设计
2.1 ETCD 集群的核心架构
ETCD 采用多节点集群架构,每个节点通过 Raft 共识算法实现数据同步。集群中的节点分为以下角色:
Leader:负责接收客户端请求、管理日志复制和提交操作。
Follower:被动接收 Leader 的日志并同步数据。
Candidate:在 Leader 失效时参与选举的临时角色。
集群的最小规模: 为保证高可用性,ETCD 集群至少需要 3 个节点(容忍 1 个节点故障)。5 节点集群可容忍 2 个节点故障。
2.2 Raft 共识算法详解
Raft 是 ETCD 实现强一致性的核心算法,其核心流程分为以下阶段:
Leader 选举
节点初始状态为 Follower。
若 Follower 在选举超时(默认 1s)内未收到 Leader 的心跳,会变为 Candidate 并发起选举。
获得超过半数节点投票的 Candidate 成为新 Leader。
示例: 假设 3 节点集群(A、B、C)中 Leader A 宕机:
B 和 C 在 1s 后成为 Candidate。
B 可能获得 B 和 C 的投票成为新 Leade