1. etcd是什么?
etcd 是一个分布式、可靠、一致的键值存储系统,专门用于保存分布式系统中的关键数据,并提供可靠的分布式协调服务。

2. etcd的核心架构
// etcd的层次化架构模型
type EtcdArchitecture struct {
// 1. 存储层
StorageLayer struct {
Backend BackendStore // BoltDB存储引擎
WAL WriteAheadLog // 预写日志
SnapshotManager SnapshotManager // 快照管理
}
// 2. Raft共识层
RaftLayer struct {
Node raft.Node // Raft节点
Storage raft.Storage // Raft存储
Transport raft.Transport // 节点间通信
}
// 3. API服务层
APILayer struct {
KVServer KVServer // 键值服务
LeaseServer LeaseServer // 租约服务
WatchServer WatchServer // 监听服务
AuthServer AuthServer // 认证服务
}
// 4. 客户端接口层
ClientLayer struct {
gRPCAPI gRPCService // gRPC接口
HTTPJSONAPI RestGateway // HTTP/JSON网关
}
}
3. Raft一致性算法深度解析
(1) Raft算法核心概念
// Raft节点的状态机
type RaftNode struct {
// 节点状态
State NodeState // Follower, Candidate, Leader
// 持久化状态
CurrentTerm int // 当前任期
VotedFor string // 投票给的节点ID
Log []LogEntry // 日志条目
// 易失性状态
CommitIndex int // 已提交的日志索引
LastApplied int // 已应用到状态机的索引
// Leader专用状态
NextIndex map[string]int // 每个follower的下一个日志索引
MatchIndex map[string]int // 每个follower已复制的日志索引
}
// 日志条目结构
type LogEntry struct {
Term int // 日志条目的任期
Index int // 日志索引
Command interface{} // 状态机命令
}
(2) Raft算法工作流程

(3) 选举过程详细代码
// Raft选举过程
func (r *RaftNode) startElection() {
// 1. 转变为Candidate状态
r.State = Candidate
r.CurrentTerm++
r.VotedFor = r.ID
// 2. 给自己投票
votesReceived := 1
// 3. 向其他节点请求投票
for _, peer := range r.peers {
go func(peer string) {
args := RequestVoteArgs{
Term: r.CurrentTerm,
CandidateID: r.ID,
LastLogIndex: r.getLastLogIndex(),
LastLogTerm: r.getLastLogTerm(),
}
var reply RequestVoteReply
r.sendRequestVote(peer, args, &reply)
if reply.VoteGranted {
r.voteCh <- true
}
}(peer)
}
// 4. 收集投票
for i := 0; i < len(r.peers); i++ {
select {
case <-r.voteCh:
votesReceived++
if votesReceived > len(r.peers)/2 {
// 成为Leader
r.becomeLeader()
return
}
case <-time.After(r.electionTimeout):
// 选举超时,重新开始
r.startElection()
return
}
}
}
4. etcd存储引擎设计
(1) 多版本并发控制(MVCC)
// etcd MVCC实现
type MVCCStore struct {
// 内存索引
keyIndex map[string]*keyIndex
// 持久化存储
backend Backend
// 当前修订版本
currentRevision int64
// 锁
mu sync.RWMutex
}
// 键的索引结构
type keyIndex struct {
key string
modified Revision // 最后一次修改的修订版本
generations []generation
}
// 修订版本
type Revision struct {
Main int64 // 主版本号
Sub int64 // 子版本号
}
// 生成(generation)表示键的创建到删除的生命周期
type generation struct {
ver int64 // 该generation中的版本数量
created Revision // 创建时的修订版本
revs []Revision // 该键的所有修订版本
}
(2) 数据存储格式
// BoltDB中的键值布局
type StorageLayout struct {
// 键的存储格式
KeyFormat: []byte("k" + key + separator + revision)
// 值的存储格式
ValueFormat: struct {
Value []byte // 实际值
LeaseID int64 // 租约ID
CreateRev int64 // 创建修订版本
ModRev int64 // 修改修订版本
Version int64 // 版本号
}
// 索引存储
IndexFormat: map[string]Revision
}
// 示例:键"foo"在修订版本5的存储
Key: []byte("kfoo\x00\x00\x00\x00\x00\x00\x00\x05")
Value: Marshal(Value{
Value: []byte("bar"),
LeaseID: 123,
CreateRev: 5,
ModRev: 5,
Version: 1,
})
5. Watch机制实现
(1) Watch工作原理
// Watch服务器实现
type watchServer struct {
// Watch流集合
watches map[WatchID]*watcher
// 事件广播通道
broadcast chan *WatchResponse
// 同步
mu sync.RWMutex
}
// 单个watcher
type watcher struct {
id WatchID
key string
prefix bool // 是否监听前缀
filters []WatchFilter
ch chan WatchResponse
cancel context.CancelFunc
}
// Watch事件处理流程
func (ws *watchServer) processEvent(event mvcc.Event) {
ws.mu.RLock()
defer ws.mu.RUnlock()
for _, w := range ws.watches {
// 检查是否匹配
if w.matches(event) {
// 应用过滤器
filteredEvent := w.filter(event)
if filteredEvent != nil {
select {
case w.ch <- filteredEvent:
default:
// channel满,可能断开连接
}
}
}
}
}
(2) Watch事件流

关键设计特点:
-
强一致性:基于Raft算法保证数据一致性
-
高可用性:多节点部署,自动故障转移
-
高性能:支持高并发读写操作
-
可观测性:丰富的监控指标和日志
-
安全性:支持TLS认证和RBAC授权