租约:如何检测你的客户端存活?
什么是租约
Leader选举本质是要解决什么问题?
- 首先要保证Leader的唯一性,确保集群不出现多个Leader,才能保证业务逻辑准确性。
- 主节点故障后,备节点应可快速感知到器异常,也就是活性检测。
- 实现活性检测有两种:被动型检测、主动型上报。
- 被动型检测:通过检测节点定时拨测Leader节点,看是否健康。
- 主动型上报:Leader节点可定期向协调服务发送"特殊心跳"回报健康状态,若其未正常发送心跳,并超过和协调服务约定
的最大存活时间后,就会被协调服务移除Leader身份标识。同时其他节点可通过协调服务,快速感知到Leader故障,发起新选举。
Lease是基于主动型上报模式,提供的一种活性检测机制。
etcd在启动的时候,创建Lessor模块的时候,它会启动两个常驻goroutine,一个是RevokeExpiredLeade任务,定时检查是否有过期Lease,
发起撤销过期的Lease操作。一个是CheckpointScheduledLease,定时触发更新Lease的剩余到期时间的操作。
Lease模块提供Grant、Revoke、LeaseTimeToLive、LeaseKeepAlive API 给客户端:
- Grant标识创建一个TTL指定秒数的Lease,Lessor会将Lease消息持久化存储在boltdb中。
- Revoke标识撤销Lease并删除其关联的数据
- LeaseTimeToLive表示获取一个Lease的有效期、剩余时间。
- LeaseKeepAlive表示为Lease续期。
Key如何关联Lease
Lease Server收到请求之后,完成Raft模块完成同步,Apply模块通过Lessor模块的Grant接口执行日志内容。
Lessor 的Grant接口会把Lease保存到内存的ItemMap数据结构中,然后持久化Lease保存到boltdb的Lease bucket,
返回一个唯一的LeaseID的client。
etcd重启后,如何知道每个Lease上关联了那些Key?
etcd的MVCC模块在持久化存储key-value的时候,保存到boltdb的value是个结构体(mvccpb.KeyValue),重启的时候,
重建关联各个Lease的key集合列表。
如何优化Lease续期性能
Lease续期是将Lease的过期时间更新为当前系统时间加其TTL。关键问题在于续期的性能能否满足业务诉求。
etcd v3 做了调整:
- TTL属性转移到Lease上,同时协议从HTTP/1.x优化为gRPC协议。
- 不同key若TTL相同,可复用同一个Lease,显著减少Lease数。通过gRPC HTTP/2 实现了多路复用,流式传输,
同一个连接可支持多个Lease续期,大大减少了连接数。
如何高效淘汰过期Lease
淘汰过期Lease的工作由Lessor模块的一个异步goroutine模块,定期从最小堆中取出已过期的Lease,执行删除Lease 和
其关联的key列表数据的RevokeExpiredLease任务。
etcd Lessor主循环每隔500ms执行一次撤销Lease检查(RevokeExpiredLease),每次轮询堆顶的元素,若过期则加入到待
淘汰列表,直到堆顶的Lease过期时间大于当前,则结束本轮轮询。
Leader如何通知其他Follower节点他们?
Leasor模块将已经确定过期的LeaseID,保存在一个名为expiredC的channel中,而etcd server的主循环定期channel中获取
LeaseID,发起revoke请求,通过Raft Log传递给Follower节点。各个节点收到Revoke Lease请求后,获取关联到此Lease上的
Key列表,从boltdb删除key,从Leasor的Lease Map内存中删除此Lease对象,最后还需要从boltdb的Lease bucket删除这个Lease。
为什么需要CheckPoint机制
集群Leader发生切换后,新的Leader基于Lease Map消息,按Lease过期时间构建一个最小堆的,etcd早期在重建的时候会自动给所有
Lease续期。如果Leader切换太频繁,切换时间小于Lease的TTL,会导致Lease永远无法删除,大量key堆积,db大小超过配额等。
etcd启动的时候,Leader节点后台会运行此异步任务,定期批量地将Lease剩余的TTL基于Raft Log同步给Follower节点,Follower节点
收到CheckPoint请求后,更新内存数据结构LeaseMap的剩余TTL信息。
当Leader节点收到KeepAlive请求的时候,它会通过checkpoint机制把此Lease的剩余TTL重置,并同步Follower节点,尽量确保续期后
集群各个节点的Lease剩余TTL一致性。
如果不想使用CheckPoint功能,可以通过experimental-enable-lease-checkpoint参数开关。