在 ETCD 源码学习过程,不会讲解太多的源码知识,只讲解相关的实现机制,需要关注源码细节的朋友可以自行根据文章中的提示,找到相关源码进行学习。
租赁,在 etcd 中主要用于设置 key 的有效期,主要流程:
1.获取一个 leaseId,并设置 leaseId 的 有效期,将 key 与 leaseId 绑定。
2.ectd 后台启动一个 goroutine, 定时检查过期 leaseId,并且清除。
主要文件
/lease/lease.go 定义lease & lessor相关的数据结构和方法。
/lease/lease_queue.go 实现了一个优先级队列,过期 lease 的检查会通过该优先级队列实现。
源码
主要数据结构
Checkpointer
type Checkpointer func(ctx context.Context, lc *pb.LeaseCheckpointRequest)
leassor
//leassor 管理所有的 lease,并实现过期检查、checkpoint 检查。
type lessor struct {
...
leaseMap map[LeaseID]*Lease // id->Lease
leaseExpiredNotifier *LeaseExpiredNotifier //Lease 过期优先级队列的实例
leaseCheckpointHeap LeaseQueue //Lease 检查点优先级队列的实例
itemMap map[LeaseItem]LeaseID
...
cp Checkpointer //leaseCheckpointHeap 中的数据会执行 Checkpointer 方法
b backend.Backend //持久化存储
...
expiredC chan []*Lease //过期键会被写入该通道,等待被上层处理。
...
}
//后台 goroutine,定期检查过期 Lease 和 checkpoint Lease
func (le *lessor) runLoop() {
defer close(le.doneC)
for {
le.revokeExpiredLeases() //过期键
le.checkpointScheduledLeases() //checkpoint
select {
case <-time.After(500 * time.Millisecond):
case <-le.stopC:
return
}
}
}
Lease
type Lease struct {
ID LeaseID
ttl int64 // 有效期时长,比如 10S
remainingTTL int64 // 剩余时长
expiryMu sync.RWMutex
expiry time.Time //过期时间戳, 比如当前时间是 2020-01-02 10:01:22, +10 s 就是 2020-01-02 10:01:32
mu sync.RWMutex
itemSet map[LeaseItem]struct{} //map 中的 Key 与当前 Lease 实例绑定的 LeaseItem 实例,Value 始终为空
revokec chan struct{} //Lease 被撤销时,会关闭该通道,从而实现监听效果
}
//是否过期
func (l *Lease) expired() bool {
return l.Remaining() <= 0
}
//持久化 存储到 backend 中
func (l *Lease) persistTo(b backend.Backend) {
key := int64ToBytes(int64(l.ID))
lpb := leasepb.Lease{ID: int64(l.ID), TTL: l.ttl, RemainingTTL: l.remainingTTL}
val, err := lpb.Marshal()
if err != nil {
panic("failed to marshal lease proto item")
}
b.BatchTx().Lock()
b.BatchTx().UnsafePut(leaseBucketName, key, val)
b.BatchTx().Unlock()
}
LeaseItem
//Key 是需要 Lease 需要绑定的键名。
type LeaseItem struct {
Key string
}
总结
本章主要介绍了 etcd 中 lease 的主要作用和主要的数据结构。通过 leassor/lease/leaseItem 等数据结构实现了 ectd 的租赁功能。每个 lease 有一个唯一ID,并且设置了有效期。 并且通过后台 goroutine 删除过期的 ID 数据。