diff --git a/lease/lessor.go b/lease/lessor.go index 6584a6fb488b..1609709b66f4 100644 --- a/lease/lessor.go +++ b/lease/lessor.go @@ -18,6 +18,7 @@ import ( "encoding/binary" "errors" "math" + "math/rand" "sort" "sync" "sync/atomic" @@ -491,6 +492,7 @@ func (le *lessor) initAndRecover() { itemSet: make(map[LeaseItem]struct{}), expiry: forever, revokec: make(chan struct{}), + fresh: true, } } tx.Unlock() @@ -508,6 +510,9 @@ type Lease struct { mu sync.RWMutex itemSet map[LeaseItem]struct{} revokec chan struct{} + + // 'true' when lease is just recovered + fresh bool } func (l *Lease) expired() bool { @@ -536,6 +541,19 @@ func (l *Lease) TTL() int64 { // refresh refreshes the expiry of the lease. func (l *Lease) refresh(extend time.Duration) { t := monotime.Now().Add(extend + time.Duration(l.ttl)*time.Second) + // 'fresh' lease only created from 'initAndRecover' + // randomize expiry with 士10%, to prevent such recovered + // leases of same TTL from expiring all at the same time, + if l.fresh { + var delta int64 + if l.ttl > 10 { + delta = int64(float64(l.ttl) * 0.1 * rand.Float64()) + } else { + delta = rand.Int63n(10) + } + t = t.Add(time.Duration(delta) * time.Second) + l.fresh = false + } atomic.StoreUint64((*uint64)(&l.expiry), uint64(t)) }