Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM]GC: Support keyspace level GC #51300

Open
wants to merge 99 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
026c7b1
support gc v2
ystaticy Feb 26, 2024
b7f3d48
make bazel_prepare
ystaticy Feb 27, 2024
e262183
make bazel_prepare
ystaticy Feb 27, 2024
c439e9e
fix curremtn min ts
ystaticy Feb 28, 2024
6eb412d
code format
ystaticy Mar 4, 2024
ffe2a29
add check safe point version
ystaticy Mar 6, 2024
6d2adcf
add check safe point version
ystaticy Mar 6, 2024
de5cdd1
update pd client
ystaticy Mar 7, 2024
65e2a3d
update bazel_prepare
ystaticy Mar 7, 2024
b18467b
update bazel_prepare
ystaticy Mar 7, 2024
886eddb
code format
ystaticy Mar 7, 2024
2fdfa83
code format
ystaticy Mar 7, 2024
a2c73a5
fix ut
ystaticy Mar 7, 2024
758b32b
fix ut
ystaticy Mar 7, 2024
42110ef
code format
ystaticy Mar 8, 2024
6869584
code format
ystaticy Mar 11, 2024
0d1bbea
merge master
ystaticy Mar 11, 2024
00ef880
merge master
ystaticy Mar 28, 2024
6fd972d
change func name
ystaticy Mar 29, 2024
505b1c8
code format
ystaticy Mar 29, 2024
61500f1
fix funcs name
ystaticy Apr 1, 2024
81a8e24
fix funcs name
ystaticy Apr 1, 2024
6398461
fix start tidb enable ks level gc
ystaticy Apr 3, 2024
ff47e2f
remove unused dir
ystaticy Apr 3, 2024
497a2c2
add tidb config check
ystaticy Apr 3, 2024
7c89b76
updage error info
ystaticy Apr 3, 2024
7d2a32f
code format
ystaticy Apr 3, 2024
acb8012
merge master
ystaticy Apr 3, 2024
bc2c6ca
fix bazel_build
ystaticy Apr 3, 2024
12870d3
code format
ystaticy Apr 3, 2024
4752f82
code format
ystaticy Apr 3, 2024
d18062a
Merge branch 'master' into tidb_gc_v2
ystaticy Apr 3, 2024
57b6b94
go mod tidy
ystaticy Apr 3, 2024
2370ab1
code format
ystaticy Apr 3, 2024
55b889a
code format
ystaticy Apr 14, 2024
129c937
code format
ystaticy Apr 14, 2024
60f61a2
fix variable name
ystaticy Apr 17, 2024
9990d10
fix comments
ystaticy Apr 18, 2024
ba4271a
add condition
ystaticy Apr 18, 2024
0a7cca4
fix default const
ystaticy Apr 18, 2024
dc591e0
fix code format
ystaticy Apr 21, 2024
73fab6e
fix code format
ystaticy Apr 21, 2024
a1f4c86
fix func name
ystaticy Apr 21, 2024
71b7b1b
fix code comments
ystaticy Apr 21, 2024
c9d9c7d
fix ut
ystaticy Apr 22, 2024
6758c62
fix ut
ystaticy Apr 22, 2024
a26c6f8
fix ut
ystaticy Apr 22, 2024
86d1f6a
fix check
ystaticy Apr 22, 2024
5192a05
fix code comments
ystaticy Apr 22, 2024
173be3d
fix code format
ystaticy Apr 23, 2024
0d55733
fix code comments
ystaticy Apr 23, 2024
fe412c5
fix bazel
ystaticy Apr 23, 2024
9de2764
fix code format
ystaticy Apr 23, 2024
ca7ac7e
fix code format
ystaticy Apr 23, 2024
e28001d
Merge remote-tracking branch 'origin/master' into tidb_gc_v2
ystaticy Apr 23, 2024
d97535e
fix code format
ystaticy Apr 23, 2024
87cf0a3
fix code format
ystaticy Apr 23, 2024
7644a47
fix code format
ystaticy Apr 23, 2024
19fb2cd
fix dir
ystaticy Apr 23, 2024
0db54f8
fix init
ystaticy Apr 23, 2024
335ad17
fix resolve locks
ystaticy Apr 23, 2024
6b1d431
fix init keyspace
ystaticy Apr 26, 2024
4717886
use get keysapce meta
ystaticy Apr 28, 2024
cd1808e
fix code comments
ystaticy Apr 28, 2024
a3ad336
fix get ks meta func
ystaticy Apr 28, 2024
06aed90
fix get ks meta func
ystaticy Apr 28, 2024
25f18b5
fix import
ystaticy Apr 28, 2024
9c0ebac
fix import
ystaticy Apr 28, 2024
7f5eb71
fix comments
ystaticy Apr 28, 2024
baeca73
fix comments
ystaticy Apr 28, 2024
c7e7422
fix comments
ystaticy Apr 28, 2024
51f7fc1
merge master
ystaticy Apr 28, 2024
03411c3
fix bazel
ystaticy Apr 29, 2024
73d9703
make bazel_prepare
ystaticy Apr 29, 2024
93bcfd6
fix format
ystaticy Apr 29, 2024
0fc78c9
fix ut
ystaticy Apr 29, 2024
07efad1
fix ut
ystaticy Apr 29, 2024
839cfb6
Merge remote-tracking branch 'origin/master' into tidb_gc_v2
ystaticy Apr 29, 2024
5452256
fix log
ystaticy Apr 29, 2024
759b6c5
rm bazel temp dir
ystaticy Apr 29, 2024
00b9d1f
fix log
ystaticy Apr 29, 2024
6388fe3
merge master
ystaticy Apr 29, 2024
0bbd3bd
fix resolve ks locks
ystaticy Apr 29, 2024
c058f14
fix logs, code comments
ystaticy Apr 30, 2024
43067d8
fix resolve locks
ystaticy Apr 30, 2024
b77dc94
rm bazel temp dir
ystaticy Apr 30, 2024
e4b8aaf
fix get ks id
ystaticy Apr 30, 2024
095c04e
fix const
ystaticy Apr 30, 2024
990d73b
fix code comments and logs
ystaticy May 6, 2024
c9af2d3
Unified get maxKeyspaceIDTxnRightBound
ystaticy May 6, 2024
a4c786c
fix comments
ystaticy May 6, 2024
71684e0
fix func name
ystaticy May 6, 2024
5990e54
fix func name
ystaticy May 6, 2024
1deef97
fix log
ystaticy May 6, 2024
10919f9
fix func name
ystaticy May 6, 2024
2a3f820
fix func name
ystaticy May 6, 2024
c543d86
fix comments
ystaticy May 6, 2024
b53ce1b
merge master
ystaticy Oct 27, 2024
a29b940
Merge branch 'master' into tidb_gc_v2
ystaticy Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/tidb-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ func main() {
os.Exit(0)
}
registerStores()
err := metricsutil.RegisterMetrics()
err := keyspace.InitGlobalKeyspaceMeta()
ystaticy marked this conversation as resolved.
Show resolved Hide resolved
terror.MustNil(err)
err = metricsutil.RegisterMetrics()
terror.MustNil(err)

if variable.EnableTmpStorageOnOOM.Load() {
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/infosync/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ go_library(
"//pkg/ddl/util",
"//pkg/domain/resourcegroup",
"//pkg/errno",
"//pkg/keyspace",
"//pkg/kv",
"//pkg/metrics",
"//pkg/parser/model",
Expand Down
14 changes: 12 additions & 2 deletions pkg/domain/infosync/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/pingcap/tidb/pkg/ddl/util"
"github.com/pingcap/tidb/pkg/domain/resourcegroup"
"github.com/pingcap/tidb/pkg/errno"
"github.com/pingcap/tidb/pkg/keyspace"
"github.com/pingcap/tidb/pkg/kv"
"github.com/pingcap/tidb/pkg/metrics"
"github.com/pingcap/tidb/pkg/parser/model"
Expand Down Expand Up @@ -724,12 +725,21 @@ func (is *InfoSyncer) GetMinStartTS() uint64 {
return is.minStartTS
}

func (is *InfoSyncer) getMinStartTsEtcdCli() *clientv3.Client {
if keyspace.IsCurrentKeyspaceUseKeyspaceLevelGC() {
// If keyspace use keyspace leve gc, we should use etcd client with keyspace prefix to access min start timestamp of the current keyspace.
return is.etcdCli
}
return is.unprefixedEtcdCli
}

// storeMinStartTS stores self server min start timestamp to etcd.
func (is *InfoSyncer) storeMinStartTS(ctx context.Context) error {
if is.unprefixedEtcdCli == nil {
minStartTsEtcdCli := is.getMinStartTsEtcdCli()
if minStartTsEtcdCli == nil {
return nil
}
return util.PutKVToEtcd(ctx, is.unprefixedEtcdCli, keyOpDefaultRetryCnt, is.minStartTSPath,
return util.PutKVToEtcd(ctx, minStartTsEtcdCli, keyOpDefaultRetryCnt, is.minStartTSPath,
ystaticy marked this conversation as resolved.
Show resolved Hide resolved
strconv.FormatUint(is.minStartTS, 10),
clientv3.WithLease(is.session.Lease()))
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/keyspace/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/config",
"//pkg/util",
"//pkg/util/codec",
"@com_github_pingcap_kvproto//pkg/keyspacepb",
"@com_github_pingcap_kvproto//pkg/kvrpcpb",
"@com_github_pingcap_kvproto//pkg/pdpb",
"@com_github_tikv_client_go_v2//config",
"@com_github_tikv_client_go_v2//tikv",
"@com_github_tikv_pd_client//:client",
"@org_uber_go_zap//:zap",
"@org_uber_go_zap//zapcore",
],
Expand All @@ -20,8 +26,10 @@ go_test(
srcs = ["keyspace_test.go"],
embed = [":keyspace"],
flaky = True,
shard_count = 3,
deps = [
"//pkg/config",
"//pkg/util/codec",
"@com_github_stretchr_testify//require",
],
)
159 changes: 159 additions & 0 deletions pkg/keyspace/keyspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,50 @@
package keyspace

import (
"context"
"encoding/binary"
"fmt"
"strings"
"sync/atomic"
"time"

"github.com/pingcap/kvproto/pkg/keyspacepb"
"github.com/pingcap/kvproto/pkg/kvrpcpb"
"github.com/pingcap/kvproto/pkg/pdpb"
"github.com/pingcap/tidb/pkg/config"
"github.com/pingcap/tidb/pkg/util"
"github.com/pingcap/tidb/pkg/util/codec"
tikvconfig "github.com/tikv/client-go/v2/config"
"github.com/tikv/client-go/v2/tikv"
pd "github.com/tikv/pd/client"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

const (
// tidbKeyspaceEtcdPathPrefix is the keyspace prefix for etcd namespace
tidbKeyspaceEtcdPathPrefix = "/keyspaces/tidb/"

// KeyspaceMetaConfigGCManagementType is gc management type in keyspace meta config.
KeyspaceMetaConfigGCManagementType = "gc_management_type"
Copy link
Contributor Author

@ystaticy ystaticy Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must set KeyspaceMetaConfigGCManagementType and KeyspaceMetaConfigGCManagementTypeKeyspaceLevelGC here, to fix import cycle.

// KeyspaceMetaConfigGCManagementTypeKeyspaceLevelGC is a type of GC management in keyspace meta config, it means this keyspace will calculate GC safe point by its own.
KeyspaceMetaConfigGCManagementTypeKeyspaceLevelGC = "keyspace_level_gc"
// KeyspaceMetaConfigGCManagementTypeGlobalGC is a type of GC management in keyspace meta config, it means this keyspace will use GC safe point by global GC.
KeyspaceMetaConfigGCManagementTypeGlobalGC = "global_gc"

// maxKeyspaceID is the maximum keyspace id that can be created, no keyspace can be created greater than this value.
maxKeyspaceID = 0xffffff

// keyspaceTxnModePrefix is txn data prefix of keyspace.
keyspaceTxnModePrefix byte = 'x'
)

// CodecV1 represents api v1 codec.
var CodecV1 = tikv.NewCodecV1(tikv.ModeTxn)

// globalKeyspaceMeta is the keyspace meta of the current TiDB, if TiDB without set "keyspace-name" then globalKeyspaceMeta.Load() == nil.
var globalKeyspaceMeta atomic.Pointer[keyspacepb.KeyspaceMeta]

// MakeKeyspaceEtcdNamespace return the keyspace prefix path for etcd namespace
func MakeKeyspaceEtcdNamespace(c tikv.Codec) string {
if c.GetAPIVersion() == kvrpcpb.APIVersion_V1 {
Expand Down Expand Up @@ -69,3 +96,135 @@ func WrapZapcoreWithKeyspace() zap.Option {
return core
})
}

// IsCurrentKeyspaceUseKeyspaceLevelGC return true if globalKeyspaceMeta not nil and globalKeyspaceMeta config has "gc_management_type" = "keyspace_level_gc".
func IsCurrentKeyspaceUseKeyspaceLevelGC() bool {
return IsKeyspaceUseKeyspaceLevelGC(GetCurrentKeyspaceMeta())
}

// IsKeyspaceUseKeyspaceLevelGC return true if keyspace meta config has "gc_management_type" = "keyspace_level_gc".
func IsKeyspaceUseKeyspaceLevelGC(keyspaceMeta *keyspacepb.KeyspaceMeta) bool {
if keyspaceMeta == nil {
return false
}
if val, ok := keyspaceMeta.Config[KeyspaceMetaConfigGCManagementType]; ok {
return val == KeyspaceMetaConfigGCManagementTypeKeyspaceLevelGC
}
return false
}

// IsCurrentKeyspaceUseGlobalGC return true if TiDB set 'keyspace-name' and use global gc.
func IsCurrentKeyspaceUseGlobalGC() bool {
if GetCurrentKeyspaceMeta() == nil {
return true
}
if val, ok := GetCurrentKeyspaceMeta().Config[KeyspaceMetaConfigGCManagementType]; ok {
return val == KeyspaceMetaConfigGCManagementTypeGlobalGC
}
return true
}

// GetKeyspaceTxnLeftBound return the keyspace txn left boundary.
func GetKeyspaceTxnLeftBound(keyspaceID uint32) []byte {
keyspaceIDBytes := make([]byte, 4)
binary.BigEndian.PutUint32(keyspaceIDBytes, keyspaceID)

// The first byte is keyspaceTxnModePrefix, and the next three bytes are converted from uint32
txnLeftBound := codec.EncodeBytes(nil, append([]byte{keyspaceTxnModePrefix}, keyspaceIDBytes[1:]...))
return txnLeftBound
}

// GetKeyspaceTxnRange return the keyspace txn left boundary and txn right boundary.
func GetKeyspaceTxnRange(keyspaceID uint32) ([]byte, []byte) {
// Get keyspace txn left boundary
txnLeftBound := GetKeyspaceTxnLeftBound(keyspaceID)

var txnRightBound []byte
if keyspaceID == maxKeyspaceID {
// Directly set the right boundary of maxKeyspaceID to be {keyspaceTxnModePrefix + 1, 0, 0, 0}
maxKeyspaceIDTxnRightBound := [4]byte{keyspaceTxnModePrefix + 1, 0, 0, 0}
txnRightBound = codec.EncodeBytes(nil, maxKeyspaceIDTxnRightBound[:])
} else {
// The right boundary of the specified keyspace is the left boundary of keyspaceID + 1.
txnRightBound = GetKeyspaceTxnLeftBound(keyspaceID + 1)
}

return txnLeftBound, txnRightBound
}

// InitGlobalKeyspaceMeta is used to get the keyspace meta from PD during TiDB startup and set global keyspace meta.
func InitGlobalKeyspaceMeta() error {
cfg := config.GetGlobalConfig()
if IsKeyspaceNameEmpty(GetKeyspaceNameBySettings()) {
return nil
}
pdAddrs, _, _, err := tikvconfig.ParsePath("tikv://" + cfg.Path)
if err != nil {
return err
}
timeoutSec := time.Duration(cfg.PDClient.PDServerTimeout) * time.Second
pdCli, err := pd.NewClient(pdAddrs, pd.SecurityOption{
CAPath: cfg.Security.ClusterSSLCA,
CertPath: cfg.Security.ClusterSSLCert,
KeyPath: cfg.Security.ClusterSSLKey,
}, pd.WithCustomTimeoutOption(timeoutSec))
if err != nil {
return err
}
defer pdCli.Close()

keyspaceMeta, err := GetKeyspaceMeta(pdCli, cfg.KeyspaceName)

setCurrentKeyspaceMeta(keyspaceMeta)
return err
}

// GetKeyspaceMeta return keyspace meta of the given keyspace name.
func GetKeyspaceMeta(pdCli pd.Client, keyspaceName string) (*keyspacepb.KeyspaceMeta, error) {
// Load Keyspace meta with retry.
var keyspaceMeta *keyspacepb.KeyspaceMeta
err := util.RunWithRetry(util.DefaultMaxRetries, util.RetryInterval, func() (bool, error) {
var errInner error
keyspaceMeta, errInner = pdCli.LoadKeyspace(context.TODO(), keyspaceName)
// Retry when pd not bootstrapped or if keyspace not exists.
if IsNotBootstrappedError(errInner) || IsKeyspaceNotExistError(errInner) {
return true, errInner
}
// Do not retry when success or encountered unexpected error.
return false, errInner
})
if err != nil {
return nil, err
}

return keyspaceMeta, nil
}

// IsNotBootstrappedError returns true if the error is pd not bootstrapped error.
func IsNotBootstrappedError(err error) bool {
if err == nil {
return false
}
return strings.Contains(err.Error(), pdpb.ErrorType_NOT_BOOTSTRAPPED.String())
}

// IsKeyspaceNotExistError returns true the error is caused by keyspace not exists.
func IsKeyspaceNotExistError(err error) bool {
if err == nil {
return false
}
return strings.Contains(err.Error(), pdpb.ErrorType_ENTRY_NOT_FOUND.String())
}

// GetCurrentKeyspaceMeta return global keyspace meta if TiDB set "keyspace-name"
func GetCurrentKeyspaceMeta() *keyspacepb.KeyspaceMeta {
v := globalKeyspaceMeta.Load()
if v == nil {
return nil
}
return v
}

func setCurrentKeyspaceMeta(ks *keyspacepb.KeyspaceMeta) {
globalKeyspaceMeta.Store(ks)
}
15 changes: 15 additions & 0 deletions pkg/keyspace/keyspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"testing"

"github.com/pingcap/tidb/pkg/config"
"github.com/pingcap/tidb/pkg/util/codec"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -50,3 +51,17 @@ func TestNoKeyspaceNameSet(t *testing.T) {
require.Equal(t, "", getKeyspaceName)
require.Equal(t, true, IsKeyspaceNameEmpty(getKeyspaceName))
}

func TestGetKeyspaceRange(t *testing.T) {
leftBound, rightBound := GetKeyspaceTxnRange(1)
expectLeftBound := codec.EncodeBytes(nil, []byte{'x', 0, 0, 1})
expectRightBound := codec.EncodeBytes(nil, []byte{'x', 0, 0, 2})
require.Equal(t, expectLeftBound, leftBound)
require.Equal(t, expectRightBound, rightBound)

maxKeyspaceIDLeftBound, maxKeyspaceIDRightBound := GetKeyspaceTxnRange(maxKeyspaceID)
expectMaxKeyspaceIDLeftBound := codec.EncodeBytes(nil, []byte{'x', 0xff, 0xff, 0xff})
maxKeyspaceIDexpectRightBound := codec.EncodeBytes(nil, []byte{'y', 0, 0, 0})
require.Equal(t, expectMaxKeyspaceIDLeftBound, maxKeyspaceIDLeftBound)
require.Equal(t, maxKeyspaceIDexpectRightBound, maxKeyspaceIDRightBound)
}
4 changes: 4 additions & 0 deletions pkg/kv/interface_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ func newMockTxn() Transaction {
// mockStorage is used to start a must commit-failed txn.
type mockStorage struct{}

func (s *mockStorage) CurrentAllTSOKeyspaceGroupMinTs() (uint64, error) {
return 0, nil
}

func (s *mockStorage) GetCodec() tikv.Codec {
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/kv/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,8 @@ type Storage interface {
UUID() string
// CurrentVersion returns current max committed version with the given txnScope (local or global).
CurrentVersion(txnScope string) (Version, error)
// CurrentAllTSOKeyspaceGroupMinTs returns current minimum ts from all TSO keyspace groups.
CurrentAllTSOKeyspaceGroupMinTs() (uint64, error)
// GetOracle gets a timestamp oracle client.
GetOracle() oracle.Oracle
// SupportDeleteRange gets the storage support delete range or not.
Expand Down
1 change: 1 addition & 0 deletions pkg/store/driver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ go_library(
importpath = "github.com/pingcap/tidb/pkg/store/driver",
visibility = ["//visibility:public"],
deps = [
"//pkg/keyspace",
"//pkg/kv",
"//pkg/metrics",
"//pkg/sessionctx/variable",
Expand Down
Loading