etcd核心架构与设计原理简单介绍

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授权

相关推荐
WindrunnerMax6 分钟前
以轻量 LoopAgent 替代 RAG 实现文档检索
人工智能·架构·github
l1t7 分钟前
DeepSeek总结的有符号、无符号、未对齐:从汇编到 SQL 的教训
汇编·数据库·sql
天远Date Lab10 分钟前
零信任架构实战:基于天远风控经营异常预警构建自动化商业园区租户巡检网关
大数据·人工智能·架构·自动化
麦壳饼23 分钟前
SonnetDB SQL Cookbook:常用查询模式速查
数据库·sonnetdb
范中勤1 小时前
适配器模式(Adapter Pattern):原理、场景与 LLM 多厂商工程落地
设计模式·架构·langchain·适配器模式·多厂商
for_ever_love__1 小时前
LangChain Text-to-SQL:让不会写 SQL 的人查数据库
数据库·sql·langchain·大模型·agent·rag·问答
梦想不只是梦与想1 小时前
SQLAlchemy:查询与操作 (三)
数据库·python·sqlalchemy
木子n11 小时前
软件架构设计实战-架构18.从 Classic 到 Adaptive:SOA 架构在 MATLAB 里的模样
架构·autosar·性能工程·soa架构
Aric_Jones1 小时前
WAL / CDC / 复制槽 /位点
数据库·oracle
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】基建三件套:gflags + gtest + spdlog 源码编译安装与实战入门
linux·网络·数据库·c++·微服务·log4j