*: refresh the lease TTL correctly when a leader is elected.

The new leader needs to refresh with an extened TTL to gracefully handle
the potential concurrent leader issue. Clients might still send keep alive
to old leader until the old leader itself gives up leadership at most after
an election timeout.
This commit is contained in:
Xiang Li 2016-03-13 20:19:47 -07:00
parent de03dbf632
commit e9a0a103e5
4 changed files with 16 additions and 11 deletions

View File

@ -134,6 +134,10 @@ func (c *ServerConfig) ReqTimeout() time.Duration {
return 5*time.Second + 2*time.Duration(c.ElectionTicks)*time.Duration(c.TickMs)*time.Millisecond
}
func (c *ServerConfig) electionTimeout() time.Duration {
return time.Duration(c.ElectionTicks) * time.Duration(c.TickMs) * time.Millisecond
}
func (c *ServerConfig) peerDialTimeout() time.Duration {
// 1s for queue wait and system delay
// + one RTT, which is smaller than 1/5 election timeout

View File

@ -165,7 +165,7 @@ func (r *raftNode) start(s *EtcdServer) {
// it promotes or demotes instead of modifying server directly.
syncC = r.s.SyncTicker
if r.s.lessor != nil {
r.s.lessor.Promote()
r.s.lessor.Promote(r.s.cfg.electionTimeout())
}
// TODO: remove the nil checking
// current test utility does not provide the stats

View File

@ -78,7 +78,8 @@ type Lessor interface {
// Promote promotes the lessor to be the primary lessor. Primary lessor manages
// the expiration and renew of leases.
Promote()
// Newly promoted lessor renew the TTL of all lease to extend + previous TTL.
Promote(extend time.Duration)
// Demote demotes the lessor from being the primary lessor.
Demote()
@ -188,7 +189,7 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
}
if le.primary {
l.refresh()
l.refresh(0)
} else {
l.forever()
}
@ -240,7 +241,7 @@ func (le *lessor) Renew(id LeaseID) (int64, error) {
return -1, ErrLeaseNotFound
}
l.refresh()
l.refresh(0)
return l.TTL, nil
}
@ -253,7 +254,7 @@ func (le *lessor) Lookup(id LeaseID) *Lease {
return nil
}
func (le *lessor) Promote() {
func (le *lessor) Promote(extend time.Duration) {
le.mu.Lock()
defer le.mu.Unlock()
@ -261,7 +262,7 @@ func (le *lessor) Promote() {
// refresh the expiries of all leases.
for _, l := range le.leaseMap {
l.refresh()
l.refresh(extend)
}
}
@ -452,11 +453,11 @@ func (l Lease) removeFrom(b backend.Backend) {
// refresh refreshes the expiry of the lease. It extends the expiry at least
// minLeaseTTL second.
func (l *Lease) refresh() {
func (l *Lease) refresh(extend time.Duration) {
if l.TTL < minLeaseTTL {
l.TTL = minLeaseTTL
}
l.expiry = time.Now().Add(time.Second * time.Duration(l.TTL))
l.expiry = time.Now().Add(extend + time.Second*time.Duration(l.TTL))
}
// forever sets the expiry of lease to be forever.
@ -491,7 +492,7 @@ func (fl *FakeLessor) Attach(id LeaseID, items []LeaseItem) error { return nil }
func (fl *FakeLessor) Detach(id LeaseID, items []LeaseItem) error { return nil }
func (fl *FakeLessor) Promote() {}
func (fl *FakeLessor) Promote(extend time.Duration) {}
func (fl *FakeLessor) Demote() {}

View File

@ -34,7 +34,7 @@ func TestLessorGrant(t *testing.T) {
defer be.Close()
le := newLessor(be)
le.Promote()
le.Promote(0)
l, err := le.Grant(1, 1)
if err != nil {
@ -128,7 +128,7 @@ func TestLessorRenew(t *testing.T) {
defer os.RemoveAll(dir)
le := newLessor(be)
le.Promote()
le.Promote(0)
l, err := le.Grant(1, 5)
if err != nil {