Skip to content

Commit 5b6d489

Browse files
authored
keyspace: Asynchronously pre-allocate keyspaces (#9019)
close #9022 keyspace: Asynchronously pre-allocate keyspaces to improve startup performance (mainly for test). Signed-off-by: Ping Yu <[email protected]>
1 parent 9092ccc commit 5b6d489

File tree

12 files changed

+108
-47
lines changed

12 files changed

+108
-47
lines changed

pkg/gc/gc_state_manager_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ func newGCStateManagerForTest(t *testing.T) (storage *endpoint.StorageEndpoint,
104104
Name: "ks1",
105105
Config: map[string]string{"gc_management_type": "global"},
106106
CreateTime: time.Now().Unix(),
107-
IsPreAlloc: false,
108107
})
109108
re.NoError(err)
110109
re.Equal(uint32(1), ks1.Id)
@@ -113,7 +112,6 @@ func newGCStateManagerForTest(t *testing.T) (storage *endpoint.StorageEndpoint,
113112
Name: "ks2",
114113
Config: map[string]string{"gc_management_type": "keyspace_level"},
115114
CreateTime: time.Now().Unix(),
116-
IsPreAlloc: false,
117115
})
118116
re.NoError(err)
119117
re.Equal(uint32(2), ks2.Id)
@@ -122,7 +120,6 @@ func newGCStateManagerForTest(t *testing.T) (storage *endpoint.StorageEndpoint,
122120
Name: "ks3",
123121
Config: map[string]string{},
124122
CreateTime: time.Now().Unix(),
125-
IsPreAlloc: false,
126123
})
127124
re.NoError(err)
128125
re.Equal(uint32(3), ks3.Id)

pkg/keyspace/keyspace.go

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ type CreateKeyspaceRequest struct {
105105
Config map[string]string
106106
// CreateTime is the timestamp used to record creation time.
107107
CreateTime int64
108-
// IsPreAlloc indicates whether the keyspace is pre-allocated when the cluster starts.
109-
IsPreAlloc bool
110108
}
111109

112110
// NewKeyspaceManager creates a Manager of keyspace related data.
@@ -167,24 +165,28 @@ func (manager *Manager) Bootstrap() error {
167165
// Initialize pre-alloc keyspace.
168166
preAlloc := manager.config.GetPreAlloc()
169167
for _, keyspaceName := range preAlloc {
170-
config, err := manager.kgm.GetKeyspaceConfigByKind(endpoint.Basic)
171-
if err != nil {
172-
return err
173-
}
174-
req := &CreateKeyspaceRequest{
175-
Name: keyspaceName,
176-
CreateTime: now,
177-
IsPreAlloc: true,
178-
Config: config,
179-
}
180-
keyspace, err := manager.CreateKeyspace(req)
181-
// Ignore the keyspaceExists error for the same reason as saving default keyspace.
182-
if err != nil && err != errs.ErrKeyspaceExists {
183-
return err
184-
}
185-
if err := manager.kgm.UpdateKeyspaceForGroup(endpoint.Basic, config[TSOKeyspaceGroupIDKey], keyspace.GetId(), opAdd); err != nil {
186-
return err
187-
}
168+
go func() {
169+
config, err := manager.kgm.GetKeyspaceConfigByKind(endpoint.Basic)
170+
if err != nil {
171+
log.Error("[keyspace] failed to get keyspace config for pre-alloc keyspace", zap.String("keyspaceName", keyspaceName), zap.Error(err))
172+
return
173+
}
174+
req := &CreateKeyspaceRequest{
175+
Name: keyspaceName,
176+
CreateTime: now,
177+
Config: config,
178+
}
179+
keyspace, err := manager.CreateKeyspace(req)
180+
// Ignore the keyspaceExists error for the same reason as saving default keyspace.
181+
if err != nil && err != errs.ErrKeyspaceExists {
182+
log.Error("[keyspace] failed to create pre-alloc keyspace", zap.String("keyspaceName", keyspaceName), zap.Error(err))
183+
return
184+
}
185+
if err := manager.kgm.UpdateKeyspaceForGroup(endpoint.Basic, config[TSOKeyspaceGroupIDKey], keyspace.GetId(), opAdd); err != nil {
186+
log.Error("[keyspace] failed to update pre-alloc keyspace for group", zap.String("keyspaceName", keyspaceName), zap.Error(err))
187+
return
188+
}
189+
}()
188190
}
189191
return nil
190192
}
@@ -236,11 +238,8 @@ func (manager *Manager) CreateKeyspace(request *CreateKeyspaceRequest) (*keyspac
236238
)
237239
return nil, err
238240
}
239-
// If the request to create a keyspace is pre-allocated when the PD starts,
240-
// there is no need to wait for the region split, because TiKV has not started.
241-
waitRegionSplit := !request.IsPreAlloc && manager.config.ToWaitRegionSplit()
242241
// Split keyspace region.
243-
err = manager.splitKeyspaceRegion(newID, waitRegionSplit)
242+
err = manager.splitKeyspaceRegion(newID, manager.config.ToWaitRegionSplit())
244243
if err != nil {
245244
err2 := manager.store.RunInTxn(manager.ctx, func(txn kv.Txn) error {
246245
idPath := keypath.KeyspaceIDPath(request.Name)
@@ -535,7 +534,6 @@ func (manager *Manager) UpdateKeyspaceConfig(name string, mutations []*Mutation)
535534
}
536535
return nil
537536
})
538-
539537
if err != nil {
540538
log.Warn("[keyspace] failed to update keyspace config",
541539
zap.Uint32("keyspace-id", meta.GetId()),

pkg/keyspace/keyspace_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ func makeCreateKeyspaceRequests(count int) []*CreateKeyspaceRequest {
113113
testConfig2: "200",
114114
},
115115
CreateTime: now,
116-
IsPreAlloc: true, // skip wait region split
117116
}
118117
}
119118
return requests

server/apiv2/handlers/keyspace.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ func CreateKeyspace(c *gin.Context) {
8080
Name: createParams.Name,
8181
Config: createParams.Config,
8282
CreateTime: time.Now().Unix(),
83-
IsPreAlloc: false,
8483
}
8584
meta, err := manager.CreateKeyspace(req)
8685
if err != nil {

server/testutil.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ func NewTestSingleConfig(c *assertutil.Checker) *config.Config {
9393
})
9494

9595
c.AssertNil(cfg.Adjust(nil, false))
96+
cfg.Keyspace.WaitRegionSplit = false
9697

9798
return cfg
9899
}

tests/cluster.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ var (
6565
WaitLeaderCheckInterval = 500 * time.Millisecond
6666
// WaitLeaderRetryTimes represents the maximum number of loops of WaitLeader.
6767
WaitLeaderRetryTimes = 100
68+
69+
// WaitPreAllocKeyspacesInterval represents the time interval of WaitPreAllocKeyspaces running check.
70+
WaitPreAllocKeyspacesInterval = 500 * time.Millisecond
71+
// WaitPreAllocKeyspacesRetryTimes represents the maximum number of loops of WaitPreAllocKeyspaces.
72+
WaitPreAllocKeyspacesRetryTimes = 100
6873
)
6974

7075
// TestServer is only for test.
@@ -379,6 +384,12 @@ func (s *TestServer) BootstrapCluster() error {
379384
if resp.GetHeader().GetError() != nil {
380385
return errors.New(resp.GetHeader().GetError().String())
381386
}
387+
388+
err = s.waitPreAllocKeyspaces()
389+
if err != nil {
390+
return err
391+
}
392+
382393
return nil
383394
}
384395

@@ -395,6 +406,48 @@ func (s *TestServer) WaitLeader() bool {
395406
return false
396407
}
397408

409+
func (s *TestServer) waitPreAllocKeyspaces() error {
410+
keyspaces := s.GetConfig().Keyspace.PreAlloc
411+
if len(keyspaces) == 0 {
412+
return nil
413+
}
414+
415+
manager := s.GetKeyspaceManager()
416+
idx := 0
417+
Outer:
418+
for range WaitPreAllocKeyspacesRetryTimes {
419+
for idx < len(keyspaces) {
420+
_, err := manager.LoadKeyspace(keyspaces[idx])
421+
if errors.ErrorEqual(err, errs.ErrKeyspaceNotFound) {
422+
time.Sleep(WaitPreAllocKeyspacesInterval)
423+
continue Outer
424+
}
425+
if err != nil {
426+
return errors.Trace(err)
427+
}
428+
429+
idx += 1
430+
}
431+
return nil
432+
}
433+
return errors.New("wait pre-alloc keyspaces retry limit exceeded")
434+
}
435+
436+
// GetPreAllocKeyspaceIDs returns the pre-allocated keyspace IDs.
437+
func (s *TestServer) GetPreAllocKeyspaceIDs() ([]uint32, error) {
438+
keyspaces := s.GetConfig().Keyspace.PreAlloc
439+
ids := make([]uint32, 0, len(keyspaces))
440+
manager := s.GetKeyspaceManager()
441+
for _, keyspace := range keyspaces {
442+
meta, err := manager.LoadKeyspace(keyspace)
443+
if err != nil {
444+
return nil, errors.Trace(err)
445+
}
446+
ids = append(ids, meta.GetId())
447+
}
448+
return ids, nil
449+
}
450+
398451
// GetServicePrimaryAddr returns the primary address of the service.
399452
func (s *TestServer) GetServicePrimaryAddr(ctx context.Context, serviceName string) (string, bool) {
400453
return s.server.GetServicePrimaryAddr(ctx, serviceName)

tests/integrations/client/keyspace_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ func mustMakeTestKeyspaces(re *require.Assertions, server *server.Server, start
4848
testConfig2: "200",
4949
},
5050
CreateTime: now,
51-
IsPreAlloc: true, // skip wait region split
5251
})
5352
re.NoError(err)
5453
}
@@ -105,8 +104,7 @@ func mustCreateKeyspaceAtState(re *require.Assertions, server *server.Server, in
105104
meta, err := manager.CreateKeyspace(&keyspace.CreateKeyspaceRequest{
106105
Name: fmt.Sprintf("test_keyspace_%d", index),
107106
Config: nil,
108-
CreateTime: 0, // Use 0 to indicate unchanged keyspace.
109-
IsPreAlloc: true, // skip wait region split
107+
CreateTime: 0, // Use 0 to indicate unchanged keyspace.
110108
})
111109
re.NoError(err)
112110
switch state {

tests/integrations/mcs/tso/api_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ func TestTSOServerStartFirst(t *testing.T) {
139139

140140
cluster, err := tests.NewTestClusterWithKeyspaceGroup(ctx, 1, func(conf *config.Config, _ string) {
141141
conf.Keyspace.PreAlloc = []string{"k1", "k2"}
142+
conf.Keyspace.WaitRegionSplit = false
142143
})
143144
defer cluster.Destroy()
144145
re.NoError(err)

tests/integrations/mcs/tso/keyspace_group_manager_test.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ func TestTwiceSplitKeyspaceGroup(t *testing.T) {
543543
conf.Keyspace.PreAlloc = []string{
544544
"keyspace_a", "keyspace_b",
545545
}
546+
conf.Keyspace.WaitRegionSplit = false
546547
})
547548
re.NoError(err)
548549
defer tc.Destroy()
@@ -736,10 +737,12 @@ func TestGetTSOImmediately(t *testing.T) {
736737
re.NoError(failpoint.Enable("github.com/tikv/pd/pkg/tso/fastGroupSplitPatroller", `return(true)`))
737738

738739
// Init PD config but not start.
740+
keyspaces := []string{
741+
"keyspace_a", "keyspace_b",
742+
}
739743
tc, err := tests.NewTestClusterWithKeyspaceGroup(ctx, 1, func(conf *config.Config, _ string) {
740-
conf.Keyspace.PreAlloc = []string{
741-
"keyspace_a", "keyspace_b",
742-
}
744+
conf.Keyspace.PreAlloc = keyspaces
745+
conf.Keyspace.WaitRegionSplit = false
743746
})
744747
re.NoError(err)
745748
defer tc.Destroy()
@@ -783,14 +786,17 @@ func TestGetTSOImmediately(t *testing.T) {
783786
return p0 == kg0.Members[0].Address && p1 == kg1.Members[1].Address
784787
}, testutil.WithWaitFor(5*time.Second), testutil.WithTickInterval(50*time.Millisecond))
785788

786-
apiCtx := pd.NewAPIContextV2("keyspace_b") // its keyspace id is 2.
787-
cli, err := pd.NewClientWithAPIContext(ctx, apiCtx,
788-
caller.TestComponent,
789-
[]string{pdAddr}, pd.SecurityOption{})
790-
re.NoError(err)
791-
_, _, err = cli.GetTS(ctx)
792-
re.NoError(err)
793-
cli.Close()
789+
for _, name := range keyspaces {
790+
apiCtx := pd.NewAPIContextV2(name)
791+
cli, err := pd.NewClientWithAPIContext(ctx, apiCtx,
792+
caller.TestComponent,
793+
[]string{pdAddr}, pd.SecurityOption{})
794+
re.NoError(err)
795+
_, _, err = cli.GetTS(ctx)
796+
re.NoError(err)
797+
cli.Close()
798+
}
799+
794800
re.NoError(failpoint.Disable("github.com/tikv/pd/pkg/tso/fastPrimaryPriorityCheck"))
795801
re.NoError(failpoint.Disable("github.com/tikv/pd/pkg/keyspace/acceleratedAllocNodes"))
796802
re.NoError(failpoint.Disable("github.com/tikv/pd/pkg/tso/fastGroupSplitPatroller"))

tests/server/keyspace/keyspace_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func (suite *keyspaceTestSuite) SetupTest() {
5757
suite.cancel = cancel
5858
cluster, err := tests.NewTestCluster(ctx, 3, func(conf *config.Config, _ string) {
5959
conf.Keyspace.PreAlloc = preAllocKeyspace
60+
conf.Keyspace.WaitRegionSplit = false
6061
})
6162
suite.cluster = cluster
6263
re.NoError(err)
@@ -86,7 +87,6 @@ func (suite *keyspaceTestSuite) TestRegionLabeler() {
8687
keyspaces[i], err = manager.CreateKeyspace(&keyspace.CreateKeyspaceRequest{
8788
Name: fmt.Sprintf("test_keyspace_%d", i),
8889
CreateTime: now,
89-
IsPreAlloc: true, // skip wait region split
9090
})
9191
re.NoError(err)
9292
}

0 commit comments

Comments
 (0)