Skip to content

Commit d473bf9

Browse files
add meta service group fallback ratio (tikv#393)
* add fallback ratio Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * fix typo Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * Update server/config/config.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix lint Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * fix lint Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * Update server/config/config.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * handle comment Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * clean Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> * Update pkg/keyspace/meta_service_group.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update server/config/config.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update pkg/keyspace/meta_service_group.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d22a567 commit d473bf9

File tree

7 files changed

+125
-26
lines changed

7 files changed

+125
-26
lines changed

pkg/keyspace/keyspace.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ type Config interface {
8383
GetAutoAssignMetaServiceGroups() bool
8484
SetMetaServiceGroups(map[string]string)
8585
GetMetaServiceGroups() map[string]string
86+
GetMetaServiceGroupsFallbackRatio() float64
87+
SetMetaServiceGroupsFallbackRatio(float64)
8688
}
8789

8890
// Manager manages keyspace related data.
@@ -244,6 +246,7 @@ func (manager *Manager) UpdateConfig(cfg Config) error {
244246
manager.mgm.updateConfig(
245247
cfg.GetAutoAssignMetaServiceGroups(),
246248
cfg.GetMetaServiceGroups(),
249+
cfg.GetMetaServiceGroupsFallbackRatio(),
247250
)
248251
}
249252
return manager.SetGlobalSafePointV2()
@@ -285,9 +288,16 @@ func (manager *Manager) CreateKeyspace(request *CreateKeyspaceRequest) (*keyspac
285288
if assignToMetaServiceGroup {
286289
metaServiceGroup, err := manager.mgm.AssignToGroup(1)
287290
if err != nil {
291+
log.Error("[keyspace] failed to assign keyspace to meta-service group",
292+
zap.Uint32("keyspace-id", newID),
293+
zap.String("name", request.Name),
294+
zap.Error(err),
295+
)
288296
return nil, err
289297
}
290-
request.Config[MetaServiceGroupIDKey] = metaServiceGroup
298+
if metaServiceGroup != "" {
299+
request.Config[MetaServiceGroupIDKey] = metaServiceGroup
300+
}
291301
}
292302

293303
// Create a disabled keyspace meta for tikv-server to get the config on keyspace split.

pkg/keyspace/keyspace_test.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,15 @@ func TestKeyspaceTestSuite(t *testing.T) {
5353
}
5454

5555
type mockConfig struct {
56-
PreAlloc []string
57-
WaitRegionSplit bool
58-
DisableRawKVRegionSplit bool
59-
WaitRegionSplitTimeout typeutil.Duration
60-
CheckRegionSplitInterval typeutil.Duration
61-
EnableGlobalSafePointV2 bool
62-
AutoAssignMetaServiceGroups bool
63-
MetaServiceGroups map[string]string
56+
PreAlloc []string
57+
WaitRegionSplit bool
58+
DisableRawKVRegionSplit bool
59+
WaitRegionSplitTimeout typeutil.Duration
60+
CheckRegionSplitInterval typeutil.Duration
61+
EnableGlobalSafePointV2 bool
62+
AutoAssignMetaServiceGroups bool
63+
MetaServiceGroups map[string]string
64+
MetaServiceGroupsFallbackRatio float64
6465
}
6566

6667
func (m *mockConfig) SetEnableGlobalSafePointV2(isEnable bool) {
@@ -107,16 +108,28 @@ func (m *mockConfig) SetMetaServiceGroups(metaServiceGroups map[string]string) {
107108
m.MetaServiceGroups = metaServiceGroups
108109
}
109110

111+
func (m *mockConfig) GetMetaServiceGroupsFallbackRatio() float64 {
112+
return m.MetaServiceGroupsFallbackRatio
113+
}
114+
115+
func (m *mockConfig) SetMetaServiceGroupsFallbackRatio(ratio float64) {
116+
m.MetaServiceGroupsFallbackRatio = ratio
117+
}
118+
110119
func (suite *keyspaceTestSuite) SetupTest() {
111120
re := suite.Require()
112121
suite.ctx, suite.cancel = context.WithCancel(context.Background())
113122
store := endpoint.NewStorageEndpoint(kv.NewMemoryKV(), nil)
114123
allocator := mockid.NewIDAllocator()
124+
cfg := mockConfig{
125+
AutoAssignMetaServiceGroups: true,
126+
MetaServiceGroups: mockMetaServiceGroups(),
127+
}
115128
kgm := NewKeyspaceGroupManager(suite.ctx, store, nil)
116-
mgm := NewMetaServiceGroupManager(suite.ctx, store, true, mockMetaServiceGroups())
129+
mgm := NewMetaServiceGroupManager(suite.ctx, store, &cfg)
117130
mustEnableMetaServiceGroups(re, mgm, mockMetaServiceGroups())
118131
var err error
119-
suite.manager, err = NewKeyspaceManager(suite.ctx, store, nil, allocator, &mockConfig{}, kgm, mgm)
132+
suite.manager, err = NewKeyspaceManager(suite.ctx, store, nil, allocator, &cfg, kgm, mgm)
120133
re.NoError(err)
121134
re.NoError(kgm.Bootstrap(suite.ctx))
122135
re.NoError(suite.manager.Bootstrap())

pkg/keyspace/meta_service_group.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ package keyspace
1717
import (
1818
"context"
1919
"math"
20+
"math/rand"
2021

22+
"github.com/pingcap/log"
2123
"github.com/tikv/pd/pkg/storage/endpoint"
2224
"github.com/tikv/pd/pkg/storage/kv"
2325
"github.com/tikv/pd/pkg/utils/syncutil"
26+
"go.uber.org/zap"
2427
)
2528

2629
// MetaServiceGroupManager manages external meta-service groups.
@@ -30,20 +33,21 @@ type MetaServiceGroupManager struct {
3033
syncutil.RWMutex
3134
autoAssign bool
3235
metaServiceGroups map[string]string
36+
fallbackRatio float64
3337
}
3438

3539
// NewMetaServiceGroupManager creates a new MetaServiceGroupManager.
3640
func NewMetaServiceGroupManager(
3741
ctx context.Context,
3842
store endpoint.MetaServiceGroupStorage,
39-
autoAssign bool,
40-
metaServiceGroups map[string]string,
43+
config Config,
4144
) *MetaServiceGroupManager {
4245
return &MetaServiceGroupManager{
4346
ctx: ctx,
4447
store: store,
45-
autoAssign: autoAssign,
46-
metaServiceGroups: metaServiceGroups,
48+
autoAssign: config.GetAutoAssignMetaServiceGroups(),
49+
metaServiceGroups: config.GetMetaServiceGroups(),
50+
fallbackRatio: config.GetMetaServiceGroupsFallbackRatio(),
4751
}
4852
}
4953

@@ -100,6 +104,13 @@ func (m *MetaServiceGroupManager) PatchStatus(groupID string, patch *MetaService
100104
func (m *MetaServiceGroupManager) AssignToGroup(count int) (string, error) {
101105
m.RLock()
102106
defer m.RUnlock()
107+
if roll := rand.Float64(); roll < m.fallbackRatio {
108+
log.Info("[keyspace] fallback meta-service group assignment to PD due to fallback ratio",
109+
zap.Float64("roll", roll),
110+
zap.Float64("fallback ratio", m.fallbackRatio),
111+
)
112+
return "", nil
113+
}
103114
var (
104115
assignedGroup string
105116
assignedGroupStatus *endpoint.MetaServiceGroupStatus
@@ -119,7 +130,10 @@ func (m *MetaServiceGroupManager) AssignToGroup(count int) (string, error) {
119130
}
120131
}
121132
if assignedGroup == "" {
122-
return errNoAvailableMetaServiceGroups
133+
log.Warn("[keyspace] fallback meta-service group assignment to PD due to no available meta-service group",
134+
zap.Any("meta-service groups status", statusMap),
135+
)
136+
return nil
123137
}
124138
assignedGroupStatus.AssignmentCount += count
125139
return m.store.SaveMetaServiceGroupStatus(txn, assignedGroup, assignedGroupStatus)
@@ -187,9 +201,10 @@ func (m *MetaServiceGroupManager) GetAutoAssign() bool {
187201
}
188202

189203
// updateConfig updates currently available meta-service groups.
190-
func (m *MetaServiceGroupManager) updateConfig(autoAssign bool, metaServiceGroups map[string]string) {
204+
func (m *MetaServiceGroupManager) updateConfig(autoAssign bool, metaServiceGroups map[string]string, fallbackRatio float64) {
191205
m.Lock()
192206
defer m.Unlock()
193207
m.autoAssign = autoAssign
194208
m.metaServiceGroups = metaServiceGroups
209+
m.fallbackRatio = fallbackRatio
195210
}

pkg/keyspace/meta_service_group_test.go

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ func mockMetaServiceGroups() map[string]string {
4545
func (suite *metaServiceGroupTestSuite) SetupTest() {
4646
suite.ctx, suite.cancel = context.WithCancel(context.Background())
4747
store := endpoint.NewStorageEndpoint(kv.NewMemoryKV(), nil)
48-
suite.manager = NewMetaServiceGroupManager(suite.ctx, store, true, mockMetaServiceGroups())
48+
cfg := mockConfig{
49+
AutoAssignMetaServiceGroups: true,
50+
MetaServiceGroups: mockMetaServiceGroups(),
51+
}
52+
suite.manager = NewMetaServiceGroupManager(suite.ctx, store, &cfg)
4953
}
5054

5155
func (suite *metaServiceGroupTestSuite) TearDownTest() {
@@ -62,9 +66,10 @@ func (suite *metaServiceGroupTestSuite) TestInitialState() {
6266
re.Zero(status.AssignmentCount)
6367
re.False(status.Enabled)
6468
}
65-
// Assign should return error due to no available groups.
66-
_, err = suite.manager.AssignToGroup(1)
67-
re.Error(err)
69+
// Assignment should fallback to PD
70+
group, err := suite.manager.AssignToGroup(1)
71+
re.NoError(err)
72+
re.Empty(group)
6873
}
6974

7075
func (suite *metaServiceGroupTestSuite) TestAssignToGroup() {
@@ -165,7 +170,7 @@ func (suite *metaServiceGroupTestSuite) TestUpdateEndpoints() {
165170
newMap := map[string]string{
166171
"foo": "foo.bar.local",
167172
}
168-
suite.manager.updateConfig(true, newMap)
173+
suite.manager.updateConfig(true, newMap, 0)
169174
config := map[string]string{MetaServiceGroupIDKey: "foo"}
170175
suite.manager.AttachEndpoints(config)
171176
re.Equal("foo.bar.local", config[MetaServiceGroupAddressesKey], "should read from updated metaServiceGroups map")
@@ -191,7 +196,7 @@ func (suite *metaServiceGroupTestSuite) TestUpdateEndpointsAndUpdateAssignment()
191196
// Add a new group "etcd-group-3"
192197
newMap := mockMetaServiceGroups()
193198
newMap["etcd-group-3"] = "etcd-group-3.tidb-serverless.cluster.svc.local"
194-
suite.manager.updateConfig(true, newMap)
199+
suite.manager.updateConfig(true, newMap, 0)
195200

196201
// Move the assignment from the originally assigned group to "etcd-group-3"
197202
err = suite.manager.UpdateAssignment(assigned, "etcd-group-3")
@@ -212,3 +217,44 @@ func (suite *metaServiceGroupTestSuite) TestUpdateEndpointsAndUpdateAssignment()
212217
re.Equal(0, statusMap[groupID].AssignmentCount, "other original groups should remain at 0")
213218
}
214219
}
220+
221+
func (suite *metaServiceGroupTestSuite) TestFallbackRatio() {
222+
re := suite.Require()
223+
for groupID := range mockMetaServiceGroups() {
224+
enable := true
225+
re.NoError(suite.manager.PatchStatus(groupID, &MetaServiceGroupStatusPatch{
226+
Enabled: &enable,
227+
}))
228+
}
229+
// Fallback ratio defaults to 0, all keyspace should be assigned to a group.
230+
for range 10 {
231+
assigned, err := suite.manager.AssignToGroup(1)
232+
re.NoError(err)
233+
re.NotEmpty(assigned, "expected AssignToGroup to return a non-empty group")
234+
}
235+
// Fallback ratio set to 0.5, some keyspace should be assigned to a group, some should fallback.
236+
batchSize := 100
237+
expectedFallbackRatio := 0.5
238+
suite.manager.fallbackRatio = expectedFallbackRatio
239+
totalFallback := 0
240+
for range batchSize {
241+
assigned, err := suite.manager.AssignToGroup(1)
242+
re.NoError(err)
243+
if assigned == "" {
244+
totalFallback++
245+
}
246+
}
247+
re.InDelta(expectedFallbackRatio, float64(totalFallback)/float64(batchSize), 0.1)
248+
249+
// Fallback ratio set to 1, all keyspace should fallback to pd.
250+
suite.manager.fallbackRatio = 1.0
251+
totalFallback = 0
252+
for range batchSize {
253+
assigned, err := suite.manager.AssignToGroup(1)
254+
re.NoError(err)
255+
if assigned == "" {
256+
totalFallback++
257+
}
258+
}
259+
re.Equal(batchSize, totalFallback, "all keyspace should fallback to pd when fallback ratio is 1.0")
260+
}

pkg/keyspace/util.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ var (
9191
// ErrUnsupportedOperationInKeyspace is used to indicate this is an unsupported operation.
9292
ErrUnsupportedOperationInKeyspace = errors.New("it's a unsupported operation")
9393

94-
errNoAvailableMetaServiceGroups = errors.New("no available meta-service groups")
95-
errUnknownMetaServiceGroup = errors.New("unknown meta-service group")
94+
errUnknownMetaServiceGroup = errors.New("unknown meta-service group")
9695

9796
// stateTransitionTable lists all allowed next state for the given current state.
9897
// Note that transit from any state to itself is allowed for idempotence.

server/config/config.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,9 @@ type KeyspaceConfig struct {
900900
AutoAssignMetaServiceGroups bool `toml:"auto-assign-meta-service-groups" json:"auto-assign-meta-service-groups,string"`
901901
// MetaServiceGroups is the available external meta-service groups.
902902
MetaServiceGroups map[string]string `toml:"meta-service-groups" json:"meta-service-groups"`
903+
// MetaServiceGroupsFallbackRatio specifies the probability that a newly created keyspace will not be assigned a meta-service group.
904+
// Valid range is [0, 1], where 0 means no fallback and 1 means always fallback to pd only.
905+
MetaServiceGroupsFallbackRatio float64 `toml:"meta-service-groups-fallback-ratio" json:"meta-service-groups-fallback-ratio"`
903906
}
904907

905908
// Validate checks if keyspace config falls within acceptable range.
@@ -916,6 +919,9 @@ func (c *KeyspaceConfig) Validate() error {
916919
return errors.New("[keyspace] meta-service group addresses cannot be empty")
917920
}
918921
}
922+
if c.MetaServiceGroupsFallbackRatio < 0 || c.MetaServiceGroupsFallbackRatio > 1 {
923+
return errors.New("[keyspace] meta-service-groups-fallback-ratio should be in range [0, 1]")
924+
}
919925
return nil
920926
}
921927

@@ -999,3 +1005,13 @@ func (c *KeyspaceConfig) GetMetaServiceGroups() map[string]string {
9991005
func (c *KeyspaceConfig) SetMetaServiceGroups(metaServiceGroups map[string]string) {
10001006
c.MetaServiceGroups = metaServiceGroups
10011007
}
1008+
1009+
// GetMetaServiceGroupsFallbackRatio returns the fallback ratio for meta-service groups.
1010+
func (c *KeyspaceConfig) GetMetaServiceGroupsFallbackRatio() float64 {
1011+
return c.MetaServiceGroupsFallbackRatio
1012+
}
1013+
1014+
// SetMetaServiceGroupsFallbackRatio sets the fallback ratio for meta-service groups.
1015+
func (c *KeyspaceConfig) SetMetaServiceGroupsFallbackRatio(fallbackRatio float64) {
1016+
c.MetaServiceGroupsFallbackRatio = fallbackRatio
1017+
}

server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ func (s *Server) startServer(ctx context.Context) error {
513513
if s.IsAPIServiceMode() {
514514
s.keyspaceGroupManager = keyspace.NewKeyspaceGroupManager(s.ctx, s.storage, s.client)
515515
}
516-
s.metaServiceGroupManager = keyspace.NewMetaServiceGroupManager(s.ctx, s.storage, s.cfg.Keyspace.AutoAssignMetaServiceGroups, s.cfg.Keyspace.MetaServiceGroups)
516+
s.metaServiceGroupManager = keyspace.NewMetaServiceGroupManager(s.ctx, s.storage, &s.cfg.Keyspace)
517517
s.keyspaceManager, err = keyspace.NewKeyspaceManager(s.ctx, s.storage, s.cluster, keyspaceIDAllocator, &s.cfg.Keyspace, s.keyspaceGroupManager, s.metaServiceGroupManager)
518518
if err != nil {
519519
return err

0 commit comments

Comments
 (0)