写请求过程
客户端执行写请求指令
etcdctl put hello world —endpoints 192.168.1.1:12379
执行流程:
- 首先客户端通过负载均衡选择一个etcd节点发起gRPC put方法调用;
- 服务器收到请求后经过gRPC拦截器、Quota模块校验,进入KV Server模块;
- KVServer模块会根据请求方法,发起对应的API请求给Raft模块,这里是PUT api;
- Raft模块会做执行一些集群操作处理,只有leader节点能处理写请求,leader节点首先将数据持久化到WAL日志中,并且状态变成已提交;
- 其他follower会同步WAL日志;
- 各个节点的Apply模块会异步将数据更新在状态机中(boltdb).
etcd还有个buffer模块,可以保存暂未提交的数据,此时可能boltdb里面没有,但是在buffer里面可以提前拿到。可以用来提高并发效率。
Quota模块
该模块主要是做一个大小检查,校验现在的db大小还能不能保存处理该写请求的结果。超过了会有报警。
KVServer模块
KV模块主要有两个功能:
- 打包请求提案:将请求根据API的不同打包发给Raft模块。
- Preflight Check(限速、鉴权、检查):
-
限速
如果Raft模块已提交索引(commit index)超过应用到boltdb中的索引(applied index)5000,就会返回错误给client。
-
鉴权
如果使用到了用户权限功能,就会在KVServer模块开启鉴权操,判断该请求是否有权限操作。
-
大包检查
判断是否写入的包大小超过了限定大小(1.5M大小)。超过了会返回错误信息给客户端。
WAL模块
会将需要修改的数据内容持久化到WAL日志文件中,Leader也会把数据内容、leader任期号、已提交索引广播给各个follower节点。
WAL中还有一个consistent index索引是用来确保数据一致性的关键字段。
consistent index 是一个单调递增的整数,用于表示 Raft 日志中的一条记录。它在 etcd 集群中的每个节点上都是唯一的。当 etcd 集群中的一个节点收到客户端的读请求时,它会先检查自己的 consistent index 与集群中其他节点的 consistent index 是否一致。如果一致,说明该节点的数据是最新的,可以直接返回给客户端。如果不一致,说明该节点的数据可能已经过时,需要先从其他节点同步数据,然后再返回给客户端。
客户端重启恢复,确保数据一致、幂等性、提案重复问题都要通过consistent index来保证。
Apply模块
当一半以上的节点持久化WAL日志后,leader就会将该请求提案状态设置为已提交状态。leader节点的apply模块会异步将WAL日志应用到状态机。follower节点apply模块会将WAL日志持久化到boltdb模块。同时更新applied index索引。