searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

深入理解etcd一:写流程

2023-06-29 01:31:28
173
0

一 架构

下图是etcd的一张全景图。

可以看到,按照分层模型,etcd 可分为 Client 层、API 层、Raft 算法层、逻辑层和存储层。这些层的功能如下:

  • Client 层:Client 层包括 client v2 和 v3 两个大版本 API 客户端库,提供了简洁易用的 API,同时支持负载均衡、节点间故障自动转移,可
    极大降低业务使用 etcd 复杂度,提升开发效率、服务可用性。
  • API 层:API 层主要包括 client 访问 server 和 server 节点之间的通信协议。一方面,client 访问 etcd server 的 API 分为 v2
    和 v3 两个大版本。v2 API 使用 HTTP/1.x 协议,v3 API 使用 gRPC 协议。同时 v3 通过 etcd grpc-gateway 组件也支持 HTTP/1.x 协议,便于各种语言的服务调用。另一方面,server 之间通信协议,是指节点间通过 Raft 算法实现数据复制和 Leader 选举等功能时使用的 HTTP 协议。
  • Raft 算法层:Raft 算法层实现了 Leader 选举、日志复制、ReadIndex 等核心算法特性,用于保障 etcd 多个节点间的数据一致性、提升服务可用性等,是 etcd 的基石和亮点。
  • 功能逻辑层:etcd 核心特性实现层,如典型的 KVServer 模块、MVCC 模块、Auth 鉴权模块、Lease 租约模块、Compactor 压缩模块等,其中MVCC 模块主要由 treeIndex 模块和 boltdb 模块组成。
  • 存储层:存储层包含预写日志 (WAL) 模块、快照 (Snapshot) 模块、boltdb 模块。其中 WAL 可保障 etcd crash 后数据不丢失,boltdb 则保存了集群元数据和用户写入的数据。

其中,etcd-server(go.etcd.io/etcd/server/v3) 包含API层,功能逻辑层的实现。

二 写流程

下图一张etcd的端到端写入流程。

  1.  client 向etcd server发起PUT请求
  2.  etcd server的API层经过一系列处理,最后进入 v3_server.go::processInternalRaftRequestOnce方法;在里面使用Node的Step接口向raft模块提交写入的message
  3.  raft模块(raft/node.go::run()) 从步骤2提交的propc channel读取消息,并把entry写入raftLog
  4.  步骤2中 api thread等待提交到 raft 模块成功;但是此时还不能给client回复响应,还需要等待步骤5
  5.  在步骤2之前,api thread注册了等到当前写入keyid的信号;次时api thread waiting
  6.  raft模块的下一轮循环中,从raftLog获取entry,然后通过readyc 通知etcd-server 的raftLoop (etcdserver/raft.go::start) 从readyc读出entry 把它们写入applyc;并且同步写入WAL
  7.  同时,leader向follower节点同步 entry
  8.  follower节点将entry写入raftLog,给leader响应消息
  9.  leader获的多数节点确认,leader更新commitID标记entry已经被提交
  10.  leader 向follower同步commitID, 以便follower可以apply日志
  11.  etcdserver (etcdserver/server.go) 从applyc读出entry; 将日志写入mvcc KVstore
  12.  之后向api thread发信号通知写入完成(步骤5)
  13.  至此,api thread被唤醒,给client回复写入成功

三 总结

上面梳理了etcd的写入流程,可以看到涉及比较多的组件的通信,值得深入阅读源码。

下面一篇将在分析各个流程(异步同步)的基础上,解释单节点etcd可能出现的写入丢失的根因,复现方法,以及修复的逻辑。

0条评论
0 / 1000
n****m
2文章数
0粉丝数
n****m
2 文章 | 0 粉丝
n****m
2文章数
0粉丝数
n****m
2 文章 | 0 粉丝
原创

深入理解etcd一:写流程

2023-06-29 01:31:28
173
0

一 架构

下图是etcd的一张全景图。

可以看到,按照分层模型,etcd 可分为 Client 层、API 层、Raft 算法层、逻辑层和存储层。这些层的功能如下:

  • Client 层:Client 层包括 client v2 和 v3 两个大版本 API 客户端库,提供了简洁易用的 API,同时支持负载均衡、节点间故障自动转移,可
    极大降低业务使用 etcd 复杂度,提升开发效率、服务可用性。
  • API 层:API 层主要包括 client 访问 server 和 server 节点之间的通信协议。一方面,client 访问 etcd server 的 API 分为 v2
    和 v3 两个大版本。v2 API 使用 HTTP/1.x 协议,v3 API 使用 gRPC 协议。同时 v3 通过 etcd grpc-gateway 组件也支持 HTTP/1.x 协议,便于各种语言的服务调用。另一方面,server 之间通信协议,是指节点间通过 Raft 算法实现数据复制和 Leader 选举等功能时使用的 HTTP 协议。
  • Raft 算法层:Raft 算法层实现了 Leader 选举、日志复制、ReadIndex 等核心算法特性,用于保障 etcd 多个节点间的数据一致性、提升服务可用性等,是 etcd 的基石和亮点。
  • 功能逻辑层:etcd 核心特性实现层,如典型的 KVServer 模块、MVCC 模块、Auth 鉴权模块、Lease 租约模块、Compactor 压缩模块等,其中MVCC 模块主要由 treeIndex 模块和 boltdb 模块组成。
  • 存储层:存储层包含预写日志 (WAL) 模块、快照 (Snapshot) 模块、boltdb 模块。其中 WAL 可保障 etcd crash 后数据不丢失,boltdb 则保存了集群元数据和用户写入的数据。

其中,etcd-server(go.etcd.io/etcd/server/v3) 包含API层,功能逻辑层的实现。

二 写流程

下图一张etcd的端到端写入流程。

  1.  client 向etcd server发起PUT请求
  2.  etcd server的API层经过一系列处理,最后进入 v3_server.go::processInternalRaftRequestOnce方法;在里面使用Node的Step接口向raft模块提交写入的message
  3.  raft模块(raft/node.go::run()) 从步骤2提交的propc channel读取消息,并把entry写入raftLog
  4.  步骤2中 api thread等待提交到 raft 模块成功;但是此时还不能给client回复响应,还需要等待步骤5
  5.  在步骤2之前,api thread注册了等到当前写入keyid的信号;次时api thread waiting
  6.  raft模块的下一轮循环中,从raftLog获取entry,然后通过readyc 通知etcd-server 的raftLoop (etcdserver/raft.go::start) 从readyc读出entry 把它们写入applyc;并且同步写入WAL
  7.  同时,leader向follower节点同步 entry
  8.  follower节点将entry写入raftLog,给leader响应消息
  9.  leader获的多数节点确认,leader更新commitID标记entry已经被提交
  10.  leader 向follower同步commitID, 以便follower可以apply日志
  11.  etcdserver (etcdserver/server.go) 从applyc读出entry; 将日志写入mvcc KVstore
  12.  之后向api thread发信号通知写入完成(步骤5)
  13.  至此,api thread被唤醒,给client回复写入成功

三 总结

上面梳理了etcd的写入流程,可以看到涉及比较多的组件的通信,值得深入阅读源码。

下面一篇将在分析各个流程(异步同步)的基础上,解释单节点etcd可能出现的写入丢失的根因,复现方法,以及修复的逻辑。

文章来自个人专栏
弹性网络-邓治国
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0