Skip to content

Commit 1f33119

Browse files
Merge pull request #32600 from nvanbenschoten/backport2.1-31408
release-2.1: storage: replace remote proposal tracking with uncommitted log size protection
2 parents 0f151f0 + 62bb20b commit 1f33119

File tree

11 files changed

+138
-432
lines changed

11 files changed

+138
-432
lines changed

Gopkg.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/base/config.go

+29
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,23 @@ type RaftConfig struct {
447447
// begin performing log truncations.
448448
RaftLogTruncationThreshold int64
449449

450+
// RaftProposalQuota controls the maximum aggregate size of Raft commands
451+
// that a leader is allowed to propose concurrently.
452+
//
453+
// By default, the quota is set to a fraction of the Raft log truncation
454+
// threshold. In doing so, we ensure all replicas have sufficiently up to
455+
// date logs so that when the log gets truncated, the followers do not need
456+
// non-preemptive snapshots. Changing this deserves care. Too low and
457+
// everything comes to a grinding halt, too high and we're not really
458+
// throttling anything (we'll still generate snapshots).
459+
RaftProposalQuota int64
460+
461+
// RaftMaxUncommittedEntriesSize controls how large the uncommitted tail of
462+
// the Raft log can grow. The limit is meant to provide protection against
463+
// unbounded Raft log growth when quorum is lost and entries stop being
464+
// committed but continue to be proposed.
465+
RaftMaxUncommittedEntriesSize uint64
466+
450467
// RaftMaxSizePerMsg controls how many Raft log entries the leader will send to
451468
// followers in a single MsgApp.
452469
RaftMaxSizePerMsg uint64
@@ -475,6 +492,18 @@ func (cfg *RaftConfig) SetDefaults() {
475492
if cfg.RaftLogTruncationThreshold == 0 {
476493
cfg.RaftLogTruncationThreshold = defaultRaftLogTruncationThreshold
477494
}
495+
if cfg.RaftProposalQuota == 0 {
496+
// By default, set this to a fraction of RaftLogMaxSize. See the comment
497+
// on the field for the tradeoffs of setting this higher or lower.
498+
cfg.RaftProposalQuota = cfg.RaftLogTruncationThreshold / 4
499+
}
500+
if cfg.RaftMaxUncommittedEntriesSize == 0 {
501+
// By default, set this to twice the RaftProposalQuota. The logic here
502+
// is that the quotaPool should be responsible for throttling proposals
503+
// in all cases except for unbounded Raft re-proposals because it queues
504+
// efficiently instead of dropping proposals on the floor indiscriminately.
505+
cfg.RaftMaxUncommittedEntriesSize = uint64(2 * cfg.RaftProposalQuota)
506+
}
478507
if cfg.RaftMaxSizePerMsg == 0 {
479508
cfg.RaftMaxSizePerMsg = uint64(defaultRaftMaxSizePerMsg)
480509
}

pkg/storage/client_raft_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,8 @@ func TestLogGrowthWhenRefreshingPendingCommands(t *testing.T) {
11541154
sc.RaftTickInterval = 10 * time.Millisecond
11551155
// Don't timeout raft leader. We don't want leadership moving.
11561156
sc.RaftElectionTimeoutTicks = 1000000
1157+
// Reduce the max uncommitted entry size.
1158+
sc.RaftMaxUncommittedEntriesSize = 64 << 10 // 64 KB
11571159
// Disable leader transfers during leaseholder changes so that we
11581160
// can easily create leader-not-leaseholder scenarios.
11591161
sc.TestingKnobs.DisableLeaderFollowsLeaseholder = true
@@ -1232,7 +1234,7 @@ func TestLogGrowthWhenRefreshingPendingCommands(t *testing.T) {
12321234
// While a majority nodes are down, write some data.
12331235
putRes := make(chan *roachpb.Error)
12341236
go func() {
1235-
putArgs := putArgs([]byte("b"), make([]byte, 8<<10 /* 8 KB */))
1237+
putArgs := putArgs([]byte("b"), make([]byte, sc.RaftMaxUncommittedEntriesSize/8))
12361238
_, err := client.SendWrapped(context.Background(), propNode, putArgs)
12371239
putRes <- err
12381240
}()
@@ -1253,11 +1255,10 @@ func TestLogGrowthWhenRefreshingPendingCommands(t *testing.T) {
12531255
}
12541256

12551257
// Check raft log size.
1256-
const logSizeLimit = 64 << 10 // 64 KB
12571258
curlogSize := leaderRepl.GetRaftLogSize()
12581259
logSize := curlogSize - initLogSize
12591260
logSizeStr := humanizeutil.IBytes(logSize)
1260-
if logSize > logSizeLimit {
1261+
if uint64(logSize) > sc.RaftMaxUncommittedEntriesSize {
12611262
t.Fatalf("raft log size grew to %s", logSizeStr)
12621263
}
12631264
t.Logf("raft log size grew to %s", logSizeStr)

0 commit comments

Comments
 (0)