diff --git a/Documentation/op-guide/configuration.md b/Documentation/op-guide/configuration.md index 60f6b050de0..3c5db2bf9e6 100644 --- a/Documentation/op-guide/configuration.md +++ b/Documentation/op-guide/configuration.md @@ -408,6 +408,11 @@ Follow the instructions when using these flags. ## Experimental flags +### --experimental-backend-bbolt-freelist-type ++ The freelist type that etcd backend(bboltdb) uses (array and map are supported types). ++ default: array ++ env variable: ETCD_EXPERIMENTAL_BACKEND_BBOLT_FREELIST_TYPE + ### --experimental-corrupt-check-time + Duration of time between cluster corruption check passes + default: 0s diff --git a/embed/config.go b/embed/config.go index 01a61f3c90a..95189e186c0 100644 --- a/embed/config.go +++ b/embed/config.go @@ -37,6 +37,7 @@ import ( "go.etcd.io/etcd/pkg/types" "github.com/ghodss/yaml" + bolt "go.etcd.io/bbolt" "go.uber.org/zap" "go.uber.org/zap/zapcore" "golang.org/x/crypto/bcrypt" @@ -75,6 +76,8 @@ const ( // maxElectionMs specifies the maximum value of election timeout. // More details are listed in ../Documentation/tuning.md#time-parameters. maxElectionMs = 50000 + // backend freelist map type + freelistMapType = "map" ) var ( @@ -273,6 +276,8 @@ type Config struct { ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"` ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"` ExperimentalEnableV2V3 string `json:"experimental-enable-v2v3"` + // ExperimentalBackendFreelistType specifies the type of freelist that boltdb backend uses (array and map are supported types). + ExperimentalBackendFreelistType string `json:"experimental-backend-bbolt-freelist-type"` // ForceNewCluster starts a new cluster even if previously started; unsafe. ForceNewCluster bool `json:"force-new-cluster"` @@ -896,3 +901,11 @@ func (cfg *Config) getMetricsURLs() (ss []string) { } return ss } + +func parseBackendFreelistType(freelistType string) bolt.FreelistType { + if freelistType == freelistMapType { + return bolt.FreelistMapType + } + + return bolt.FreelistArrayType +} diff --git a/embed/etcd.go b/embed/etcd.go index 7cfce805bcb..5cd86df39c2 100644 --- a/embed/etcd.go +++ b/embed/etcd.go @@ -159,6 +159,8 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { return e, err } + backendFreelistType := parseBackendFreelistType(cfg.ExperimentalBackendFreelistType) + srvcfg := etcdserver.ServerConfig{ Name: cfg.Name, ClientURLs: cfg.ACUrls, @@ -182,6 +184,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { AutoCompactionMode: cfg.AutoCompactionMode, QuotaBackendBytes: cfg.QuotaBackendBytes, BackendBatchLimit: cfg.BackendBatchLimit, + BackendFreelistType: backendFreelistType, BackendBatchInterval: cfg.BackendBatchInterval, MaxTxnOps: cfg.MaxTxnOps, MaxRequestBytes: cfg.MaxRequestBytes, diff --git a/etcdmain/config.go b/etcdmain/config.go index db5ece034c2..e06d642c7e6 100644 --- a/etcdmain/config.go +++ b/etcdmain/config.go @@ -248,6 +248,7 @@ func newConfig() *config { fs.BoolVar(&cfg.ec.ExperimentalInitialCorruptCheck, "experimental-initial-corrupt-check", cfg.ec.ExperimentalInitialCorruptCheck, "Enable to check data corruption before serving any client/peer traffic.") fs.DurationVar(&cfg.ec.ExperimentalCorruptCheckTime, "experimental-corrupt-check-time", cfg.ec.ExperimentalCorruptCheckTime, "Duration of time between cluster corruption check passes.") fs.StringVar(&cfg.ec.ExperimentalEnableV2V3, "experimental-enable-v2v3", cfg.ec.ExperimentalEnableV2V3, "v3 prefix for serving emulated v2 state.") + fs.StringVar(&cfg.ec.ExperimentalBackendFreelistType, "experimental-backend-bbolt-freelist-type", cfg.ec.ExperimentalBackendFreelistType, "ExperimentalBackendFreelistType specifies the type of freelist that boltdb backend uses(array and map are supported types)") // unsafe fs.BoolVar(&cfg.ec.ForceNewCluster, "force-new-cluster", false, "Force to create a new one member cluster.") diff --git a/etcdmain/help.go b/etcdmain/help.go index 21d6e72c930..8ef6c457a18 100644 --- a/etcdmain/help.go +++ b/etcdmain/help.go @@ -200,6 +200,8 @@ Experimental feature: Duration of time between cluster corruption check passes. --experimental-enable-v2v3 '' Serve v2 requests through the v3 backend under a given prefix. + --experimental-backend-bbolt-freelist-type + ExperimentalBackendFreelistType specifies the type of freelist that boltdb backend uses(array and map are supported types). Unsafe feature: --force-new-cluster 'false' diff --git a/etcdserver/backend.go b/etcdserver/backend.go index a5f4ffa7535..7fd8d17b560 100644 --- a/etcdserver/backend.go +++ b/etcdserver/backend.go @@ -43,6 +43,7 @@ func newBackend(cfg ServerConfig) backend.Backend { cfg.Logger.Info("setting backend batch interval", zap.Duration("batch interval", cfg.BackendBatchInterval)) } } + bcfg.BackendFreelistType = cfg.BackendFreelistType bcfg.Logger = cfg.Logger if cfg.QuotaBackendBytes > 0 && cfg.QuotaBackendBytes != DefaultQuotaBytes { // permit 10% excess over quota for disarm diff --git a/etcdserver/config.go b/etcdserver/config.go index d037b83b919..b0eaf18e7b9 100644 --- a/etcdserver/config.go +++ b/etcdserver/config.go @@ -26,6 +26,7 @@ import ( "go.etcd.io/etcd/pkg/transport" "go.etcd.io/etcd/pkg/types" + bolt "go.etcd.io/bbolt" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -60,6 +61,9 @@ type ServerConfig struct { // BackendBatchLimit is the maximum operations before commit the backend transaction. BackendBatchLimit int + // BackendFreelistType is the type of the backend boltdb freelist. + BackendFreelistType bolt.FreelistType + InitialPeerURLsMap types.URLsMap InitialClusterToken string NewCluster bool diff --git a/mvcc/backend/backend.go b/mvcc/backend/backend.go index 11a1c46c7c6..3bf96afda44 100644 --- a/mvcc/backend/backend.go +++ b/mvcc/backend/backend.go @@ -110,6 +110,8 @@ type BackendConfig struct { BatchInterval time.Duration // BatchLimit is the maximum puts before flushing the BatchTx. BatchLimit int + // BackendFreelistType is the backend boltdb's freelist type. + BackendFreelistType bolt.FreelistType // MmapSize is the number of bytes to mmap for the backend. MmapSize uint64 // Logger logs backend-side operations. @@ -140,6 +142,7 @@ func newBackend(bcfg BackendConfig) *backend { *bopts = *boltOpenOptions } bopts.InitialMmapSize = bcfg.mmapSize() + bopts.FreelistType = bcfg.BackendFreelistType db, err := bolt.Open(bcfg.Path, 0600, bopts) if err != nil {