Skip to content

Commit 1205326

Browse files
authored
config: Relax limitation of tso-update-physical-interval (#5437)
ref #5440, close #5440 Minimal valid value of config item `tso-update-physical-interval` is changed to 1ms. Signed-off-by: pingyu <[email protected]>
1 parent 0433eea commit 1205326

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

server/config/config.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ type Config struct {
9191
TSOSaveInterval typeutil.Duration `toml:"tso-save-interval" json:"tso-save-interval"`
9292

9393
// The interval to update physical part of timestamp. Usually, this config should not be set.
94-
// It's only useful for test purposes.
95-
// This config is only valid in 50ms to 10s. If it's configured too long or too short, it will
94+
// At most 1<<18 (262144) TSOs can be generated in the interval. The smaller the value, the
95+
// more TSOs provided, and at the same time consuming more CPU time.
96+
// This config is only valid in 1ms to 10s. If it's configured too long or too short, it will
9697
// be automatically clamped to the range.
9798
TSOUpdatePhysicalInterval typeutil.Duration `toml:"tso-update-physical-interval" json:"tso-update-physical-interval"`
9899

@@ -252,7 +253,7 @@ const (
252253
// DefaultTSOUpdatePhysicalInterval is the default value of the config `TSOUpdatePhysicalInterval`.
253254
DefaultTSOUpdatePhysicalInterval = 50 * time.Millisecond
254255
maxTSOUpdatePhysicalInterval = 10 * time.Second
255-
minTSOUpdatePhysicalInterval = 50 * time.Millisecond
256+
minTSOUpdatePhysicalInterval = 1 * time.Millisecond
256257

257258
defaultLogFormat = "text"
258259

server/config/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ address = "localhost:9090"
261261

262262
// Test clamping TSOUpdatePhysicalInterval value
263263
cfgData = `
264-
tso-update-physical-interval = "10ms"
264+
tso-update-physical-interval = "500ns"
265265
`
266266
cfg = NewConfig()
267267
meta, err = toml.Decode(cfgData, &cfg)

server/tso/tso.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ const (
4444
maxLogical = int64(1 << 18)
4545
// MaxSuffixBits indicates the max number of suffix bits.
4646
MaxSuffixBits = 4
47+
// jetLagWarningThreshold is the warning threshold of jetLag in `timestampOracle.UpdateTimestamp`.
48+
// In case of small `updatePhysicalInterval`, the `3 * updatePhysicalInterval` would also is small,
49+
// and trigger unnecessary warnings about clock offset.
50+
// It's an empirical value.
51+
jetLagWarningThreshold = 150 * time.Millisecond
4752
)
4853

4954
// tsoObject is used to store the current TSO in memory with a RWMutex lock.
@@ -321,7 +326,7 @@ func (t *timestampOracle) UpdateTimestamp(leadership *election.Leadership) error
321326
tsoCounter.WithLabelValues("save", t.dcLocation).Inc()
322327

323328
jetLag := typeutil.SubRealTimeByWallClock(now, prevPhysical)
324-
if jetLag > 3*t.updatePhysicalInterval {
329+
if jetLag > 3*t.updatePhysicalInterval && jetLag > jetLagWarningThreshold {
325330
log.Warn("clock offset", zap.Duration("jet-lag", jetLag), zap.Time("prev-physical", prevPhysical), zap.Time("now", now), zap.Duration("update-physical-interval", t.updatePhysicalInterval))
326331
tsoCounter.WithLabelValues("slow_save", t.dcLocation).Inc()
327332
}
@@ -385,7 +390,7 @@ func (t *timestampOracle) getTS(leadership *election.Leadership, count uint32, s
385390
return pdpb.Timestamp{}, errs.ErrGenerateTimestamp.FastGenByArgs("timestamp in memory has been reset")
386391
}
387392
if resp.GetLogical() >= maxLogical {
388-
log.Error("logical part outside of max logical interval, please check ntp time",
393+
log.Warn("logical part outside of max logical interval, please check ntp time, or adjust config item `tso-update-physical-interval`",
389394
zap.Reflect("response", resp),
390395
zap.Int("retry-count", i), errs.ZapError(errs.ErrLogicOverflow))
391396
tsoCounter.WithLabelValues("logical_overflow", t.dcLocation).Inc()

tests/server/tso/global_tso_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"github.com/stretchr/testify/require"
2929
"github.com/tikv/pd/pkg/grpcutil"
3030
"github.com/tikv/pd/pkg/testutil"
31+
"github.com/tikv/pd/pkg/typeutil"
32+
"github.com/tikv/pd/server/config"
3133
"github.com/tikv/pd/server/tso"
3234
"github.com/tikv/pd/tests"
3335
)
@@ -185,3 +187,48 @@ func TestDelaySyncTimestamp(t *testing.T) {
185187
re.NotNil(checkAndReturnTimestampResponse(re, req, resp))
186188
re.NoError(failpoint.Disable("github.com/tikv/pd/server/tso/delaySyncTimestamp"))
187189
}
190+
191+
func TestLogicalOverflow(t *testing.T) {
192+
re := require.New(t)
193+
194+
runCase := func(updateInterval time.Duration) {
195+
ctx, cancel := context.WithCancel(context.Background())
196+
defer cancel()
197+
cluster, err := tests.NewTestCluster(ctx, 1, func(conf *config.Config, serverName string) {
198+
conf.TSOUpdatePhysicalInterval = typeutil.Duration{Duration: updateInterval}
199+
})
200+
defer cluster.Destroy()
201+
re.NoError(err)
202+
re.NoError(cluster.RunInitialServers())
203+
cluster.WaitLeader()
204+
205+
leaderServer := cluster.GetServer(cluster.GetLeader())
206+
grpcPDClient := testutil.MustNewGrpcClient(re, leaderServer.GetAddr())
207+
clusterID := leaderServer.GetClusterID()
208+
209+
tsoClient, err := grpcPDClient.Tso(ctx)
210+
re.NoError(err)
211+
defer tsoClient.CloseSend()
212+
213+
begin := time.Now()
214+
for i := 0; i < 2; i += 1 { // the 2nd request may (but not must) overflow, as max logical interval is 262144
215+
req := &pdpb.TsoRequest{
216+
Header: testutil.NewRequestHeader(clusterID),
217+
Count: 150000,
218+
DcLocation: tso.GlobalDCLocation,
219+
}
220+
re.NoError(tsoClient.Send(req))
221+
_, err = tsoClient.Recv()
222+
re.NoError(err)
223+
}
224+
elapse := time.Since(begin)
225+
if updateInterval >= 20*time.Millisecond { // on small interval, the physical may update before overflow
226+
re.GreaterOrEqual(elapse, updateInterval)
227+
}
228+
re.Less(elapse, updateInterval+20*time.Millisecond) // additional 20ms for gRPC latency
229+
}
230+
231+
for _, updateInterval := range []int{1, 5, 30, 50} {
232+
runCase(time.Duration(updateInterval) * time.Millisecond)
233+
}
234+
}

0 commit comments

Comments
 (0)