Skip to content

Commit 656336e

Browse files
authored
Merge pull request #18570 from lucasrod16/18538-backport-3.5
Backport TestLessorRenewExtendPileup race condition fix for release-3.5
2 parents 9293b83 + 64a19e4 commit 656336e

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

server/lease/lessor.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ var v3_6 = semver.Version{Major: 3, Minor: 6}
4444
var (
4545
forever = time.Time{}
4646

47-
// maximum number of leases to revoke per second; configurable for tests
48-
leaseRevokeRate = 1000
47+
// default number of leases to revoke per second; configurable for tests
48+
defaultLeaseRevokeRate = 1000
4949

5050
// maximum number of lease checkpoints recorded to the consensus log per second; configurable for tests
5151
leaseCheckpointRate = 1000
@@ -172,6 +172,9 @@ type lessor struct {
172172
// requests for shorter TTLs are extended to the minimum TTL.
173173
minLeaseTTL int64
174174

175+
// maximum number of leases to revoke per second
176+
leaseRevokeRate int
177+
175178
expiredC chan []*Lease
176179
// stopC is a channel whose closure indicates that the lessor should be stopped.
177180
stopC chan struct{}
@@ -200,6 +203,8 @@ type LessorConfig struct {
200203
CheckpointInterval time.Duration
201204
ExpiredLeasesRetryInterval time.Duration
202205
CheckpointPersist bool
206+
207+
leaseRevokeRate int
203208
}
204209

205210
func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) Lessor {
@@ -209,19 +214,24 @@ func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorCon
209214
func newLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) *lessor {
210215
checkpointInterval := cfg.CheckpointInterval
211216
expiredLeaseRetryInterval := cfg.ExpiredLeasesRetryInterval
217+
leaseRevokeRate := cfg.leaseRevokeRate
212218
if checkpointInterval == 0 {
213219
checkpointInterval = defaultLeaseCheckpointInterval
214220
}
215221
if expiredLeaseRetryInterval == 0 {
216222
expiredLeaseRetryInterval = defaultExpiredleaseRetryInterval
217223
}
224+
if leaseRevokeRate == 0 {
225+
leaseRevokeRate = defaultLeaseRevokeRate
226+
}
218227
l := &lessor{
219228
leaseMap: make(map[LeaseID]*Lease),
220229
itemMap: make(map[LeaseItem]LeaseID),
221230
leaseExpiredNotifier: newLeaseExpiredNotifier(),
222231
leaseCheckpointHeap: make(LeaseQueue, 0),
223232
b: b,
224233
minLeaseTTL: cfg.MinLeaseTTL,
234+
leaseRevokeRate: leaseRevokeRate,
225235
checkpointInterval: checkpointInterval,
226236
expiredLeaseRetryInterval: expiredLeaseRetryInterval,
227237
checkpointPersist: cfg.CheckpointPersist,
@@ -474,7 +484,7 @@ func (le *lessor) Promote(extend time.Duration) {
474484
le.scheduleCheckpointIfNeeded(l)
475485
}
476486

477-
if len(le.leaseMap) < leaseRevokeRate {
487+
if len(le.leaseMap) < le.leaseRevokeRate {
478488
// no possibility of lease pile-up
479489
return
480490
}
@@ -488,7 +498,7 @@ func (le *lessor) Promote(extend time.Duration) {
488498
expires := 0
489499
// have fewer expires than the total revoke rate so piled up leases
490500
// don't consume the entire revoke limit
491-
targetExpiresPerSecond := (3 * leaseRevokeRate) / 4
501+
targetExpiresPerSecond := (3 * le.leaseRevokeRate) / 4
492502
for _, l := range leases {
493503
remaining := l.Remaining()
494504
if remaining > nextWindow {
@@ -627,7 +637,7 @@ func (le *lessor) revokeExpiredLeases() {
627637
var ls []*Lease
628638

629639
// rate limit
630-
revokeLimit := leaseRevokeRate / 2
640+
revokeLimit := le.leaseRevokeRate / 2
631641

632642
le.mu.RLock()
633643
if le.isPrimary() {

server/lease/lessor_test.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -291,17 +291,15 @@ func TestLessorRenewWithCheckpointer(t *testing.T) {
291291
// TestLessorRenewExtendPileup ensures Lessor extends leases on promotion if too many
292292
// expire at the same time.
293293
func TestLessorRenewExtendPileup(t *testing.T) {
294-
oldRevokeRate := leaseRevokeRate
295-
defer func() { leaseRevokeRate = oldRevokeRate }()
294+
leaseRevokeRate := 10
296295
lg := zap.NewNop()
297-
leaseRevokeRate = 10
298296

299297
dir, be := NewTestBackend(t)
300298
defer os.RemoveAll(dir)
301299

302-
le := newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL})
300+
le := newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL, leaseRevokeRate: leaseRevokeRate})
303301
ttl := int64(10)
304-
for i := 1; i <= leaseRevokeRate*10; i++ {
302+
for i := 1; i <= le.leaseRevokeRate*10; i++ {
305303
if _, err := le.Grant(LeaseID(2*i), ttl); err != nil {
306304
t.Fatal(err)
307305
}
@@ -318,7 +316,7 @@ func TestLessorRenewExtendPileup(t *testing.T) {
318316
bcfg.Path = filepath.Join(dir, "be")
319317
be = backend.New(bcfg)
320318
defer be.Close()
321-
le = newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL})
319+
le = newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL, leaseRevokeRate: leaseRevokeRate})
322320
defer le.Stop()
323321

324322
// extend after recovery should extend expiration on lease pile-up
@@ -333,11 +331,11 @@ func TestLessorRenewExtendPileup(t *testing.T) {
333331

334332
for i := ttl; i < ttl+20; i++ {
335333
c := windowCounts[i]
336-
if c > leaseRevokeRate {
337-
t.Errorf("expected at most %d expiring at %ds, got %d", leaseRevokeRate, i, c)
334+
if c > le.leaseRevokeRate {
335+
t.Errorf("expected at most %d expiring at %ds, got %d", le.leaseRevokeRate, i, c)
338336
}
339-
if c < leaseRevokeRate/2 {
340-
t.Errorf("expected at least %d expiring at %ds, got %d", leaseRevokeRate/2, i, c)
337+
if c < le.leaseRevokeRate/2 {
338+
t.Errorf("expected at least %d expiring at %ds, got %d", le.leaseRevokeRate/2, i, c)
341339
}
342340
}
343341
}

0 commit comments

Comments
 (0)