一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
etcd的gRPC通信接口
Client定义
type Client struct{
Cluster // 向集群里增加etcd服务端节点之类,属于管理员操作
KV // 我们主要使用的功能,即操作K-V
Lease // 租约相关操作,比如申请一个TTL=10s的租约
Auth // 管理ETCD的用户和权限 属于管理员操作
Watcher // 观察订阅,从而监听最新的数据变化
Maintenance // 维护etcd,比如主动迁移etcd的leader节点,管理员操作
UserName string // 认证的用户名
Password string // 认证的密码
}
etcd的核心API
- KV Service :创建、更新获取和删除键值对
- Watch Service :监视键的更改
- Lease Service : 实现键值对过期客户端用来续租保持心跳
- Lock Service : etcd提供分布式共享锁支持
- Election Service :暴露客户端选举机制
读写过程概述
读请求
客户端通过负载均衡选择一个etcd节点,发出读请求,API接口层提供Range RPC方法,etcd服务端拦截gRPC 读取请求后调用相应的处理器处理请求。
- etcdctl会创建一个clientv3库对象,选取一个合适的etcd节点
- 调用KV Server模块的Range RPC方法,发送请求
- 拦截器拦截,主要做一些校验和监控
- 调用KV Server模块的Range接口获取数据
线性读:线性读是相对串行读来讲的概念,集群模式下会有多个etcd节点,不同节点可能存在一致性问题,串行读直接返回状态数据,不需要与集群中其他节点交互,这种方式速度快,开销小,但是会存在数据不一致的情况。 线性读需要集群成员之间达成共识,存在开销,响应速度相对满,但是能保证数据的一致性. etcd默认读模式是线性读。
etcd中的查询请求,查询单个键或一组键以及查询数量,到底层实际会调用Range keys方法。
- 在treeIndex中根据BTree快速查询该键对应索引项keyIndex,索引项中包含Revision
- 据查询到的版本号信息Revision,在Backend的缓存Buffer中用二分查找,如命中则直接返回
- 若缓存中不符合条件,在BlotDB中查找(基于BlotDB的索引),查询后返回键值对信息
写请求
客户端通过负载均衡选择一个etcd节点发起写请求etcd服务器拦截gRPC写请求,涉及校验和监控后,KV Server 向 raft模块发提案,内容为写入数据命令,经网络转发,当集群中多数节点达成一致,持久化数据后,状态变成MVCC模块执行提案内容。
- 客户端通过负载均衡算法选择一个etcd节点,发起gRPC调用
- etcd server收到客户端请求
- 经过gRPC拦截,Quota校验,Quota模块用于校验etcd db文件大小是否超过配额。
- KV Server模块将请求发送给本模块中的raft,负责与etcd raft模块进行通信发起一个提案,命令为put,foo,bar,即使用put方法将foo更新为bar
- 提案经过转发之后,半数节点成功持久化
- MVCC模块更新状态机