etcd 学习系列(二):集群架构 —— 3 节点是如何工作的

前言

上一篇文章我们知道了 etcd 是一个分布式的 key-value 存储。但"分布式"具体是怎么实现的?3 台机器组成一个集群,它们之间是怎么分工合作的?

这篇文章,我们来拆解 etcd 集群的架构。


一、3 个节点,3 种角色

在 etcd 集群中,每个节点在任意时刻都处于以下三种角色之一:

角色 职责 数量
Leader(领导者) 处理所有写请求,定期发心跳给 follower 1 个
Follower(追随者) 被动同步 leader 的数据,处理读请求 2 个
Candidate(候选者) 选举期间的临时角色 0 或 多个
复制代码
┌──────────────┐       ┌──────────────┐       ┌──────────────┐
│   Leader     │       │   Follower   │       │   Follower   │
│   (主)      │←───→│   (从)      │←───→│   (从)      │
│   处理写请求  │       │   同步数据    │       │   同步数据    │
│   发心跳      │       │   处理读请求  │       │   处理读请求  │
└──────────────┘       └──────────────┘       └──────────────┘

查看集群成员

bash 复制代码
etcdctl member list

输出示例:

复制代码
member xxxx: name=node-1 peerURLs=http://10.0.0.1:2380 clientURLs=http://10.0.0.1:2379 isLeader=false
member yyyy: name=node-2 peerURLs=http://10.0.0.2:2380 clientURLs=http://10.0.0.2:2379 isLeader=true
member zzzz: name=node-3 peerURLs=http://10.0.0.3:2380 clientURLs=http://10.0.0.3:2379 isLeader=false

从 isLeader 字段可以知道谁是当前的 leader。


二、两个端口:2379 和 2380

etcd 集群使用两个端口通信:

端口 用途 类比
2379 Client 端口,给应用(客户端)用的 前台接待
2380 Peer 端口,etcd 节点之间通信用的 员工通道
复制代码
       应用(你的服务)
           │
           │ 2379(客户端连接)
           ▼
┌──────────────────────────────┐
│  etcd 集群                    │
│                              │
│  ┌──────┐  2380  ┌──────┐   │
│  │节点 A │←──────→│节点 B │   │
│  └──────┘         └──────┘   │
│      ↑               ↑       │
│      │ 2380          │ 2380  │
│      ↓               ↓       │
│  ┌──────┐                   │
│  │节点 C │                   │
│  └──────┘                   │
└──────────────────────────────┘

关键理解:节点之间不需要 2379

etcd 节点之间通过 2380 同步数据、选举 leader。不需要互开 2379,因为 2379 是给客户端用的。

复制代码
etcd 节点之间:
  ├── 2380 → ✅ 必须互开,用于数据同步、选举 leader
  └── 2379 → ❌ 不需要互开,这是给客户端用的

三、防火墙策略实践

在实际部署时,建议用 firewalld 或 iptables 限制端口访问:

bash 复制代码
# 允许 etcd 节点之间 2380 通信
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.1" port protocol="tcp" port="2380" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.2" port protocol="tcp" port="2380" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.3" port protocol="tcp" port="2380" accept'

# 允许应用访问 2379
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="2379" accept'

firewall-cmd --reload

四、写请求的完整流程

当应用要修改一个配置值时,完整的流程是这样的:

复制代码
1. 应用发请求到任意节点(比如节点 A)
2. 如果节点 A 不是 leader:
   → 节点 A 把请求转发给 leader(通过 2380 或 2379,取决于客户端版本)
3. leader 收到请求:
   a. 写入自己的 WAL 日志
   b. 并行发给所有 follower
4. follower 收到 → 写入自己的 WAL → 回复 leader "收到"
5. leader 收到过半确认(自己 + 至少 1 个 follower)→ 返回成功
6. 应用收到 "修改成功"

为什么需要"过半确认"?

复制代码
3 节点集群,quorum = 2

如果 leader 写入成功就返回,不等待 follower:
  → leader 突然宕机
  → 数据还没同步到其他节点
  → 数据丢了 ❌

如果 leader 等待过半确认:
  → leader 写入 → 同步到至少 1 个 follower → 返回成功
  → leader 宕机 → 另一个 follower 有数据 → 当选新 leader
  → 数据不丢 ✅

五、读请求:线性读 vs 串行读

etcd 支持两种读模式:

线性读(Linearizable Read)

复制代码
客户端 → 读请求 → follower → 转发给 leader
leader 确认自己还是 leader → 返回最新数据

特点:保证读到最新数据,但多了一次网络转发

串行读(Serializable Read)

复制代码
客户端 → 读请求 → 任意节点 → 直接返回自己内存中的数据

特点:性能好,但可能读到毫秒级延迟的旧数据

用哪个取决于客户端 API 版本

客户端 API 默认读模式 说明
etcd v2 API 串行读 v2 不支持线性读,固定串行
etcd v3 API 线性读 默认线性读,可改为串行读

六、查看集群状态

bash 复制代码
# 集群健康
etcdctl cluster-health

# 成员列表
etcdctl member list

# 详细状态(v3 API)
export ETCDCTL_API=3
etcdctl --endpoints=http://127.0.0.1:2379 endpoint status --write-out=table

输出示例:

复制代码
+------------------+------------------+---------+---------+-----------+-----------+------------+
|    ENDPOINT      |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+------------------+------------------+---------+---------+-----------+-----------+------------+
| 127.0.0.1:2379   | ad245981f2b01e41 |  3.3.11  |  123 MB |    false  |    12345  |   67890    |
+------------------+------------------+---------+---------+-----------+-----------+------------+
字段 含义
VERSION etcd 二进制版本
DB SIZE 数据文件大小
IS LEADER 是否 leader
RAFT TERM 第几次选举周期
RAFT INDEX 已经处理了多少条写操作

小结

etcd 集群的核心就是:3 个节点,1 个 leader,2 个 follower,2380 同步数据,2379 服务客户端。

  • 写操作必须经过 leader,需要过半确认
  • 读操作取决于 API 版本(v2 串行,v3 线性)
  • 防火墙策略:2380 节点间互开,2379 只对客户端开放

下一篇文章,我们来深入 Raft 协议------分布式一致性的核心算法。


上一篇:[etcd 学习系列(一):从业务需求出发,理解 etcd 是什么](#etcd 学习系列(一):从业务需求出发,理解 etcd 是什么)

下一篇:[etcd 学习系列(三):Raft 协议 ------ 分布式一致性就是这么简单](#etcd 学习系列(三):Raft 协议 —— 分布式一致性就是这么简单)

相关推荐
讯捷蓝达4 分钟前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
聪明的笨猪猪15 分钟前
AI应用架构选型:架构师的核心决策困境与权衡
经验分享·面试·架构
疯华整猫2 小时前
被杀掉之后:我把 Android 的「唤起 + 常驻」重做了一遍
前端·面试·架构
Dawson Zhu2 小时前
【LLM推理与Serving⑤】Prefix Cache前缀缓存:让重复prompt不再重复计算
人工智能·语言模型·架构·aigc·agi
薛定谔的悦3 小时前
光储充一体机从主控到执行单元的双层架构
数据库·mongodb·架构
爱和冰阔落3 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
lisanmengmeng3 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
Android系统攻城狮4 小时前
Linux FFmpeg深度解析之av_write_frame调用流程与实战(三十三)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
上火的金鱼妹4 小时前
k8s生产实际问题排查(网关,数据库读写等)
运维·服务器
孙克旭_4 小时前
k8s基础组件与创建资源
运维·docker·容器·kubernetes