Allow overlapping blocks by default (#11331)

Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>
This commit is contained in:
Ganesh Vernekar 2022-09-28 19:17:54 +05:30 committed by GitHub
parent 448cfda6c1
commit f34aeefe6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 9 additions and 70 deletions

View file

@ -312,8 +312,10 @@ func main() {
serverOnlyFlag(a, "storage.tsdb.no-lockfile", "Do not create lockfile in data directory."). serverOnlyFlag(a, "storage.tsdb.no-lockfile", "Do not create lockfile in data directory.").
Default("false").BoolVar(&cfg.tsdb.NoLockfile) Default("false").BoolVar(&cfg.tsdb.NoLockfile)
serverOnlyFlag(a, "storage.tsdb.allow-overlapping-blocks", "Allow overlapping blocks, which in turn enables vertical compaction and vertical query merge."). // TODO: Remove in Prometheus 3.0.
Default("false").BoolVar(&cfg.tsdb.AllowOverlappingBlocks) var b bool
serverOnlyFlag(a, "storage.tsdb.allow-overlapping-blocks", "[DEPRECATED] This flag has no effect. Overlapping blocks are enabled by default now.").
Default("true").Hidden().BoolVar(&b)
serverOnlyFlag(a, "storage.tsdb.wal-compression", "Compress the tsdb WAL."). serverOnlyFlag(a, "storage.tsdb.wal-compression", "Compress the tsdb WAL.").
Hidden().Default("true").BoolVar(&cfg.tsdb.WALCompression) Hidden().Default("true").BoolVar(&cfg.tsdb.WALCompression)
@ -1008,7 +1010,6 @@ func main() {
"NoLockfile", cfg.tsdb.NoLockfile, "NoLockfile", cfg.tsdb.NoLockfile,
"RetentionDuration", cfg.tsdb.RetentionDuration, "RetentionDuration", cfg.tsdb.RetentionDuration,
"WALSegmentSize", cfg.tsdb.WALSegmentSize, "WALSegmentSize", cfg.tsdb.WALSegmentSize,
"AllowOverlappingBlocks", cfg.tsdb.AllowOverlappingBlocks,
"WALCompression", cfg.tsdb.WALCompression, "WALCompression", cfg.tsdb.WALCompression,
) )
@ -1531,7 +1532,6 @@ type tsdbOptions struct {
RetentionDuration model.Duration RetentionDuration model.Duration
MaxBytes units.Base2Bytes MaxBytes units.Base2Bytes
NoLockfile bool NoLockfile bool
AllowOverlappingBlocks bool
WALCompression bool WALCompression bool
HeadChunksWriteQueueSize int HeadChunksWriteQueueSize int
StripeSize int StripeSize int
@ -1550,8 +1550,7 @@ func (opts tsdbOptions) ToTSDBOptions() tsdb.Options {
RetentionDuration: int64(time.Duration(opts.RetentionDuration) / time.Millisecond), RetentionDuration: int64(time.Duration(opts.RetentionDuration) / time.Millisecond),
MaxBytes: int64(opts.MaxBytes), MaxBytes: int64(opts.MaxBytes),
NoLockfile: opts.NoLockfile, NoLockfile: opts.NoLockfile,
AllowOverlappingCompaction: opts.AllowOverlappingBlocks, AllowOverlappingCompaction: true,
AllowOverlappingQueries: opts.AllowOverlappingBlocks,
WALCompression: opts.WALCompression, WALCompression: opts.WALCompression,
HeadChunksWriteQueueSize: opts.HeadChunksWriteQueueSize, HeadChunksWriteQueueSize: opts.HeadChunksWriteQueueSize,
StripeSize: opts.StripeSize, StripeSize: opts.StripeSize,

View file

@ -117,8 +117,6 @@ func TestBackfillRuleIntegration(t *testing.T) {
} }
opts := tsdb.DefaultOptions() opts := tsdb.DefaultOptions()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := tsdb.Open(tmpDir, nil, nil, opts, nil) db, err := tsdb.Open(tmpDir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -246,8 +244,6 @@ func TestBackfillLabels(t *testing.T) {
} }
opts := tsdb.DefaultOptions() opts := tsdb.DefaultOptions()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := tsdb.Open(tmpDir, nil, nil, opts, nil) db, err := tsdb.Open(tmpDir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)

View file

@ -155,7 +155,7 @@ Backfilling can be used via the Promtool command line. Promtool will write the b
promtool tsdb create-blocks-from openmetrics <input file> [<output directory>] promtool tsdb create-blocks-from openmetrics <input file> [<output directory>]
``` ```
After the creation of the blocks, move it to the data directory of Prometheus. If there is an overlap with the existing blocks in Prometheus, the flag `--storage.tsdb.allow-overlapping-blocks` needs to be set. Note that any backfilled data is subject to the retention configured for your Prometheus server (by time or size). After the creation of the blocks, move it to the data directory of Prometheus. If there is an overlap with the existing blocks in Prometheus, the flag `--storage.tsdb.allow-overlapping-blocks` needs to be set for Prometheus versions v2.38 and below. Note that any backfilled data is subject to the retention configured for your Prometheus server (by time or size).
#### Longer Block Durations #### Longer Block Durations
@ -189,7 +189,7 @@ $ promtool tsdb create-blocks-from rules \
The recording rule files provided should be a normal [Prometheus rules file](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/). The recording rule files provided should be a normal [Prometheus rules file](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/).
The output of `promtool tsdb create-blocks-from rules` command is a directory that contains blocks with the historical rule data for all rules in the recording rule files. By default the output directory is `data/`. In order to make use of this new block data, the blocks must be moved to a running Prometheus instance data dir `storage.tsdb.path` that has the flag `--storage.tsdb.allow-overlapping-blocks` enabled. Once moved, the new blocks will merge with existing blocks when the next compaction runs. The output of `promtool tsdb create-blocks-from rules` command is a directory that contains blocks with the historical rule data for all rules in the recording rule files. By default, the output directory is `data/`. In order to make use of this new block data, the blocks must be moved to a running Prometheus instance data dir `storage.tsdb.path` (for Prometheus versions v2.38 and below, the flag `--storage.tsdb.allow-overlapping-blocks` must be enabled). Once moved, the new blocks will merge with existing blocks when the next compaction runs.
### Limitations ### Limitations

View file

@ -76,8 +76,7 @@ func DefaultOptions() *Options {
MinBlockDuration: DefaultBlockDuration, MinBlockDuration: DefaultBlockDuration,
MaxBlockDuration: DefaultBlockDuration, MaxBlockDuration: DefaultBlockDuration,
NoLockfile: false, NoLockfile: false,
AllowOverlappingCompaction: false, AllowOverlappingCompaction: true,
AllowOverlappingQueries: false,
WALCompression: false, WALCompression: false,
StripeSize: DefaultStripeSize, StripeSize: DefaultStripeSize,
HeadChunksWriteBufferSize: chunks.DefaultWriteBufferSize, HeadChunksWriteBufferSize: chunks.DefaultWriteBufferSize,
@ -114,18 +113,12 @@ type Options struct {
// NoLockfile disables creation and consideration of a lock file. // NoLockfile disables creation and consideration of a lock file.
NoLockfile bool NoLockfile bool
// Querying on overlapping blocks are allowed if AllowOverlappingQueries is true.
// Since querying is a required operation for TSDB, if there are going to be
// overlapping blocks, then this should be set to true.
// NOTE: Do not use this directly in DB. Use it via DB.AllowOverlappingQueries().
AllowOverlappingQueries bool
// Compaction of overlapping blocks are allowed if AllowOverlappingCompaction is true. // Compaction of overlapping blocks are allowed if AllowOverlappingCompaction is true.
// This is an optional flag for overlapping blocks. // This is an optional flag for overlapping blocks.
// The reason why this flag exists is because there are various users of the TSDB // The reason why this flag exists is because there are various users of the TSDB
// that do not want vertical compaction happening on ingest time. Instead, // that do not want vertical compaction happening on ingest time. Instead,
// they'd rather keep overlapping blocks and let another component do the overlapping compaction later. // they'd rather keep overlapping blocks and let another component do the overlapping compaction later.
// For Prometheus, this will always be enabled if overlapping queries is enabled. // For Prometheus, this will always be true.
AllowOverlappingCompaction bool AllowOverlappingCompaction bool
// WALCompression will turn on Snappy compression for records on the WAL. // WALCompression will turn on Snappy compression for records on the WAL.
@ -642,9 +635,6 @@ func validateOpts(opts *Options, rngs []int64) (*Options, []int64) {
if opts.MinBlockDuration > opts.MaxBlockDuration { if opts.MinBlockDuration > opts.MaxBlockDuration {
opts.MaxBlockDuration = opts.MinBlockDuration opts.MaxBlockDuration = opts.MinBlockDuration
} }
if opts.OutOfOrderTimeWindow > 0 {
opts.AllowOverlappingQueries = true
}
if opts.OutOfOrderCapMax <= 0 { if opts.OutOfOrderCapMax <= 0 {
opts.OutOfOrderCapMax = DefaultOutOfOrderCapMax opts.OutOfOrderCapMax = DefaultOutOfOrderCapMax
} }
@ -1368,11 +1358,6 @@ func (db *DB) reloadBlocks() (err error) {
sort.Slice(toLoad, func(i, j int) bool { sort.Slice(toLoad, func(i, j int) bool {
return toLoad[i].Meta().MinTime < toLoad[j].Meta().MinTime return toLoad[i].Meta().MinTime < toLoad[j].Meta().MinTime
}) })
if !db.AllowOverlappingQueries() {
if err := validateBlockSequence(toLoad); err != nil {
return errors.Wrap(err, "invalid block sequence")
}
}
// Swap new blocks first for subsequently created readers to be seen. // Swap new blocks first for subsequently created readers to be seen.
oldBlocks := db.blocks oldBlocks := db.blocks
@ -1398,10 +1383,6 @@ func (db *DB) reloadBlocks() (err error) {
return nil return nil
} }
func (db *DB) AllowOverlappingQueries() bool {
return db.opts.AllowOverlappingQueries || db.oooWasEnabled.Load()
}
func openBlocks(l log.Logger, dir string, loaded []*Block, chunkPool chunkenc.Pool) (blocks []*Block, corrupted map[ulid.ULID]error, err error) { func openBlocks(l log.Logger, dir string, loaded []*Block, chunkPool chunkenc.Pool) (blocks []*Block, corrupted map[ulid.ULID]error, err error) {
bDirs, err := blockDirs(dir) bDirs, err := blockDirs(dir)
if err != nil { if err != nil {
@ -1548,25 +1529,6 @@ func (db *DB) deleteBlocks(blocks map[ulid.ULID]*Block) error {
return nil return nil
} }
// validateBlockSequence returns error if given block meta files indicate that some blocks overlaps within sequence.
func validateBlockSequence(bs []*Block) error {
if len(bs) <= 1 {
return nil
}
var metas []BlockMeta
for _, b := range bs {
metas = append(metas, b.meta)
}
overlaps := OverlappingBlocks(metas)
if len(overlaps) > 0 {
return errors.Errorf("block time ranges overlap: %s", overlaps)
}
return nil
}
// TimeRange specifies minTime and maxTime range. // TimeRange specifies minTime and maxTime range.
type TimeRange struct { type TimeRange struct {
Min, Max int64 Min, Max int64

View file

@ -3976,8 +3976,6 @@ func TestOOOCompaction(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -4158,8 +4156,6 @@ func TestOOOCompactionWithNormalCompaction(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -4255,7 +4251,6 @@ func Test_Querier_OOOQuery(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds() opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = false opts.AllowOverlappingCompaction = false
series1 := labels.FromStrings("foo", "bar1") series1 := labels.FromStrings("foo", "bar1")
@ -4341,7 +4336,6 @@ func Test_ChunkQuerier_OOOQuery(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds() opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = false opts.AllowOverlappingCompaction = false
series1 := labels.FromStrings("foo", "bar1") series1 := labels.FromStrings("foo", "bar1")
@ -4435,7 +4429,6 @@ func TestOOOAppendAndQuery(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds() opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds()
opts.AllowOverlappingQueries = true
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
@ -4627,7 +4620,6 @@ func TestWBLAndMmapReplay(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds() opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds()
opts.AllowOverlappingQueries = true
db := openTestDB(t, opts, nil) db := openTestDB(t, opts, nil)
db.DisableCompactions() db.DisableCompactions()
@ -4815,8 +4807,6 @@ func TestOOOCompactionFailure(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -4956,8 +4946,6 @@ func TestWBLCorruption(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 30 opts.OutOfOrderCapMax = 30
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5104,8 +5092,6 @@ func TestOOOMmapCorruption(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderCapMax = 10 opts.OutOfOrderCapMax = 10
opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5563,8 +5549,6 @@ func TestWblReplayAfterOOODisableAndRestart(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
opts.AllowOverlappingCompaction = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5624,7 +5608,6 @@ func TestPanicOnApplyConfig(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)
@ -5673,7 +5656,6 @@ func TestDiskFillingUpAfterDisablingOOO(t *testing.T) {
opts := DefaultOptions() opts := DefaultOptions()
opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds()
opts.AllowOverlappingQueries = true
db, err := Open(dir, nil, nil, opts, nil) db, err := Open(dir, nil, nil, opts, nil)
require.NoError(t, err) require.NoError(t, err)