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

add S3 minimum part size defined by the user #17171

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f026971
add S3 minimum part sized defined by the user
rvrangel Nov 7, 2024
79e56f5
update vttablet.txt
rvrangel Nov 7, 2024
4a6af9e
fixing flags
rvrangel Nov 7, 2024
72b1c6c
go mod tidy
rvrangel Nov 7, 2024
ca0054b
VReplication: Qualify and SQL escape tables in created AutoIncrement …
mattlord Nov 7, 2024
6af219f
Skip `TestRunFailsToStartTabletManager` for now (#17167)
frouioui Nov 7, 2024
d1d0c53
Add RPC to read the statements to be executed in an unresolved prepar…
GuptaManan100 Nov 8, 2024
60394fe
Add GetTransactionInfo in VTadmin API and page (#17142)
GuptaManan100 Nov 8, 2024
23b7ef8
Fix: Update found rows pool transaction capacity dynamically via vtta…
harshit-gangal Nov 8, 2024
3ce96e8
bugfix: Handle CTEs with columns named in the CTE def (#17179)
systay Nov 8, 2024
6a910ec
Atomic Transaction `StartCommit` api to return the commit state (#17116)
harshit-gangal Nov 8, 2024
6825bc6
VTAdmin: Support for multiple DataTable accessing same URL (#17036)
beingnoble03 Nov 8, 2024
9b269d6
Fix flakiness in `TestListenerShutdown` (#17024)
frouioui Nov 8, 2024
cb94ec7
Close zookeeper topo connection on disconnect (#17136)
shanth96 Nov 8, 2024
7954280
Flakes: Address flakiness in TestZkConnClosedOnDisconnect (#17194)
mattlord Nov 9, 2024
0913b83
`engine.Reload()`: read InnoDB tables sizes including `FULLTEXT` inde…
shlomi-noach Nov 11, 2024
a16af51
Fix to prevent stopping buffering prematurely (#17013)
GuptaManan100 Nov 11, 2024
a3255b7
Online DDL: fix defer function, potential connection pool exhaustion …
shlomi-noach Nov 11, 2024
3dc1d40
Limit rare race condition in `topo.Server` (#17165)
frouioui Nov 11, 2024
ed2ac59
VReplication Flaky Test fix: TestVtctldMigrateSharded (#17182)
rohit-nayak-ps Nov 11, 2024
4efbdaa
VReplication fix Flaky e2e test TestMoveTablesBuffering (#17180)
rohit-nayak-ps Nov 11, 2024
8bdd1bd
Online DDL: `ANALYZE` the shadow table before cut-over (#17201)
shlomi-noach Nov 11, 2024
74ed73c
[main] Upgrade the Golang version to `go1.23.3` (#17199)
vitess-bot Nov 11, 2024
65220db
Update the EOL documentation (#17215)
frouioui Nov 12, 2024
8fe3453
Update Atomic Distributed Transaction Design (#17005)
harshit-gangal Nov 12, 2024
d2e726e
Online DDL: `--singleton-table` DDL strategy flag (#17169)
shlomi-noach Nov 12, 2024
200e559
e2e framework change to find empty throttler config (#17228)
harshit-gangal Nov 14, 2024
9f5aa3a
go mod update (#17227)
harshit-gangal Nov 14, 2024
c289b9c
Fix deadlock in messager and health streamer (#17230)
GuptaManan100 Nov 15, 2024
d45e7b8
Binlog: Improve ZstdInMemoryDecompressorMaxSize management (#17220)
mattlord Nov 16, 2024
3c31991
Handle MySQL handler error codes (#17252)
shlomi-noach Nov 19, 2024
115fd86
Use proper keyspace when updating the query graph of a reference DML …
frouioui Nov 19, 2024
457004a
Add support for receiving `grpc_bind_adress` on `vttestserver` (#17231)
gmpify Nov 19, 2024
fc07d3f
sqltypes: add ToTime conversion funcs (#17178)
derekperkins Nov 20, 2024
c7f241e
VReplication: recover from closed connection (#17249)
shlomi-noach Nov 20, 2024
c13f941
Tablet throttler: read and use MySQL host metrics (#16904)
shlomi-noach Nov 20, 2024
d99f2c0
Online DDL: dynamic cut-over threshold via `ALTER VITESS_MIGRATION ..…
shlomi-noach Nov 20, 2024
a06582b
Remove unused code for old START_GTID logic (#17265)
dbussink Nov 20, 2024
83420f4
PRS and ERS don't promote replicas taking backups (#16997)
ejortegau Nov 21, 2024
bf5dfaf
Fix potential deadlock in health streamer (#17261)
GuptaManan100 Nov 21, 2024
0f08ff4
PR feedback
rvrangel Nov 21, 2024
5994e0e
fix conflict
rvrangel Nov 21, 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.66.3
github.com/aws/smithy-go v1.22.0
github.com/bndr/gotabulate v1.1.2
github.com/dustin/go-humanize v1.0.1
github.com/gammazero/deque v0.2.1
github.com/google/safehtml v0.1.0
github.com/hashicorp/go-version v1.7.0
Expand Down Expand Up @@ -153,7 +154,6 @@ require (
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 // indirect
github.com/ebitengine/purego v0.8.1 // indirect
github.com/envoyproxy/go-control-plane v0.13.1 // indirect
Expand Down
1 change: 1 addition & 0 deletions go/flags/endtoend/vtbackup.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ Flags:
--remote_operation_timeout duration time to wait for a remote operation (default 15s)
--restart_before_backup Perform a mysqld clean/full restart after applying binlogs, but before taking the backup. Only makes sense to work around xtrabackup bugs.
--s3_backup_aws_endpoint string endpoint of the S3 backend (region must be provided).
--s3_backup_aws_min_partsize int Minimum part size to use, defaults to 5MiB but can be increased due to the dataset size. (default 5242880)
--s3_backup_aws_region string AWS region to use. (default "us-east-1")
--s3_backup_aws_retries int AWS request retries. (default -1)
--s3_backup_force_path_style force the s3 path style.
Expand Down
1 change: 1 addition & 0 deletions go/flags/endtoend/vtctld.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Flags:
--purge_logs_interval duration how often try to remove old logs (default 1h0m0s)
--remote_operation_timeout duration time to wait for a remote operation (default 15s)
--s3_backup_aws_endpoint string endpoint of the S3 backend (region must be provided).
--s3_backup_aws_min_partsize int Minimum part size to use, defaults to 5MiB but can be increased due to the dataset size. (default 5242880)
--s3_backup_aws_region string AWS region to use. (default "us-east-1")
--s3_backup_aws_retries int AWS request retries. (default -1)
--s3_backup_force_path_style force the s3 path style.
Expand Down
1 change: 1 addition & 0 deletions go/flags/endtoend/vttablet.txt
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ Flags:
--restore_from_backup_ts string (init restore parameter) if set, restore the latest backup taken at or before this timestamp. Example: '2021-04-29.133050'
--retain_online_ddl_tables duration How long should vttablet keep an old migrated table before purging it (default 24h0m0s)
--s3_backup_aws_endpoint string endpoint of the S3 backend (region must be provided).
--s3_backup_aws_min_partsize int Minimum part size to use, defaults to 5MiB but can be increased due to the dataset size. (default 5242880)
--s3_backup_aws_region string AWS region to use. (default "us-east-1")
--s3_backup_aws_retries int AWS request retries. (default -1)
--s3_backup_force_path_style force the s3 path style.
Expand Down
54 changes: 43 additions & 11 deletions go/vt/mysqlctl/s3backupstorage/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/s3/types"
transport "github.com/aws/smithy-go/endpoints"
"github.com/aws/smithy-go/middleware"
"github.com/dustin/go-humanize"
"github.com/spf13/pflag"

"vitess.io/vitess/go/vt/concurrency"
Expand All @@ -55,6 +56,11 @@ import (
"vitess.io/vitess/go/vt/servenv"
)

const (
sseCustomerPrefix = "sse_c:"
MaxPartSize = 1024 * 1024 * 1024 * 5 // 5GiB - limited by AWS https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html
)

var (
// AWS API region
region string
Expand Down Expand Up @@ -84,6 +90,11 @@ var (

// path component delimiter
delimiter = "/"

// minimum part size
minPartSize int64

ErrPartSize = errors.New("minimum S3 part size must be between 5MiB and 5GiB")
)

func registerFlags(fs *pflag.FlagSet) {
Expand All @@ -96,6 +107,7 @@ func registerFlags(fs *pflag.FlagSet) {
fs.BoolVar(&tlsSkipVerifyCert, "s3_backup_tls_skip_verify_cert", false, "skip the 'certificate is valid' check for SSL connections.")
fs.StringVar(&requiredLogLevel, "s3_backup_log_level", "LogOff", "determine the S3 loglevel to use from LogOff, LogDebug, LogDebugWithSigning, LogDebugWithHTTPBody, LogDebugWithRequestRetries, LogDebugWithRequestErrors.")
fs.StringVar(&sse, "s3_backup_server_side_encryption", "", "server-side encryption algorithm (e.g., AES256, aws:kms, sse_c:/path/to/key/file).")
fs.Int64Var(&minPartSize, "s3_backup_aws_min_partsize", manager.MinUploadPartSize, "Minimum part size to use, defaults to 5MiB but can be increased due to the dataset size.")
}

func init() {
Expand All @@ -109,8 +121,6 @@ type logNameToLogLevel map[string]aws.ClientLogMode

var logNameMap logNameToLogLevel

const sseCustomerPrefix = "sse_c:"

type endpointResolver struct {
r s3.EndpointResolverV2
endpoint *string
Expand Down Expand Up @@ -179,17 +189,13 @@ func (bh *S3BackupHandle) AddFile(ctx context.Context, filename string, filesize
return nil, fmt.Errorf("AddFile cannot be called on read-only backup")
}

// Calculate s3 upload part size using the source filesize
partSizeBytes := manager.DefaultUploadPartSize
if filesize > 0 {
minimumPartSize := float64(filesize) / float64(manager.MaxUploadParts)
// Round up to ensure large enough partsize
calculatedPartSizeBytes := int64(math.Ceil(minimumPartSize))
if calculatedPartSizeBytes > partSizeBytes {
partSizeBytes = calculatedPartSizeBytes
}
partSizeBytes, err := getPartSize(filesize)
if err != nil {
return nil, err
}

bh.bs.params.Logger.Infof("Using S3 upload part size: %s", humanize.IBytes(uint64(partSizeBytes)))

reader, writer := io.Pipe()
bh.waitGroup.Add(1)

Expand Down Expand Up @@ -537,6 +543,32 @@ func objName(parts ...string) string {
return res
}

// this is a helper to calculate the part size, taking into consideration the minimum part size
// passed in by an operator.
func getPartSize(filesize int64) (partSizeBytes int64, err error) {
// Calculate s3 upload part size using the source filesize
partSizeBytes = manager.DefaultUploadPartSize
if filesize > 0 {
minimumPartSize := float64(filesize) / float64(manager.MaxUploadParts)
// Round up to ensure large enough partsize
calculatedPartSizeBytes := int64(math.Ceil(minimumPartSize))
if calculatedPartSizeBytes > partSizeBytes {
partSizeBytes = calculatedPartSizeBytes
}
}

if minPartSize != 0 && partSizeBytes < minPartSize {
if minPartSize > MaxPartSize || minPartSize < manager.MinUploadPartSize { // 5GiB and 5MiB respectively
return 0, fmt.Errorf("%w, currently set to %s",
ErrPartSize, humanize.IBytes(uint64(minPartSize)),
)
}
partSizeBytes = int64(minPartSize)
}

return
}

func init() {
backupstorage.BackupStorageMap["s3"] = newS3BackupStorage()

Expand Down
65 changes: 65 additions & 0 deletions go/vt/mysqlctl/s3backupstorage/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,68 @@ func TestWithParams(t *testing.T) {
assert.NotNil(t, s3.transport.DialContext)
assert.NotNil(t, s3.transport.Proxy)
}

func TestGetPartSize(t *testing.T) {
originalMinimum := minPartSize
defer func() { minPartSize = originalMinimum }()

tests := []struct {
name string
filesize int64
minimumPartSize int64
want int64
err error
}{
{
name: "minimum - 10 MiB",
filesize: 1024 * 1024 * 10, // 10 MiB
minimumPartSize: 1024 * 1024 * 5, // 5 MiB
want: 1024 * 1024 * 5, // 5 MiB,
err: nil,
},
{
name: "below minimum - 10 MiB",
filesize: 1024 * 1024 * 10, // 10 MiB
minimumPartSize: 1024 * 1024 * 8, // 8 MiB
want: 1024 * 1024 * 8, // 8 MiB,
err: nil,
},
{
name: "above minimum - 1 TiB",
filesize: 1024 * 1024 * 1024 * 1024, // 1 TiB
minimumPartSize: 1024 * 1024 * 5, // 5 MiB
want: 109951163, // ~104 MiB
err: nil,
},
{
name: "below minimum - 1 TiB",
filesize: 1024 * 1024 * 1024 * 1024, // 1 TiB
minimumPartSize: 1024 * 1024 * 200, // 200 MiB
want: 1024 * 1024 * 200, // 200 MiB
err: nil,
},
{
name: "below S3 limits - 5 MiB",
filesize: 1024 * 1024 * 3, // 3 MiB
minimumPartSize: 1024 * 1024 * 4, // 4 MiB
want: 1024 * 1024 * 5, // 5 MiB - should always return the minimum
err: nil,
},
{
name: "above S3 limits - 5 GiB",
filesize: 1024 * 1024 * 1024 * 1024, // 1 TiB
minimumPartSize: 1024 * 1024 * 1024 * 6, // 6 GiB
want: 0,
err: ErrPartSize,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
minPartSize = tt.minimumPartSize
partSize, err := getPartSize(tt.filesize)
require.ErrorIs(t, err, tt.err)
require.Equal(t, tt.want, partSize)
})
}
}
Loading