Skip to content

Commit

Permalink
lease: randomize expiry on initial refresh call
Browse files Browse the repository at this point in the history
Randomize the very first expiry on lease recovery
to prevent recovered leases from expiring all at
the same time.

Address etcd-io#8096.

Signed-off-by: Gyu-Ho Lee <gyuhox@gmail.com>
  • Loading branch information
gyuho committed Jun 15, 2017
1 parent ee0c805 commit 58f4999
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lease/lessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/binary"
"errors"
"math"
"math/rand"
"sort"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -491,6 +492,7 @@ func (le *lessor) initAndRecover() {
itemSet: make(map[LeaseItem]struct{}),
expiry: forever,
revokec: make(chan struct{}),
fresh: true,
}
}
tx.Unlock()
Expand All @@ -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 {
Expand Down Expand Up @@ -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))
}

Expand Down

0 comments on commit 58f4999

Please sign in to comment.