Skip to content

Scheduled OOO Compaction without dependency on in-order head Compaction#11847

Open
MarkintoshZ wants to merge 6 commits intoprometheus:mainfrom
MarkintoshZ:ooo-compaction
Open

Scheduled OOO Compaction without dependency on in-order head Compaction#11847
MarkintoshZ wants to merge 6 commits intoprometheus:mainfrom
MarkintoshZ:ooo-compaction

Conversation

@MarkintoshZ
Copy link
Copy Markdown

PR for #11834

This is my first time contributing so I am unsure if I did everything right. Pointers are much appreciated!

Is it necessary to add a test for the new behavior? If so, what is the best way to test the 2-hour scheduled OOO compaction behavior?

Copy link
Copy Markdown
Member

@bboreham bboreham left a comment

Choose a reason for hiding this comment

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

Recommend you do include a test.

Comment thread tsdb/db.go Outdated
Comment thread tsdb/db.go Outdated
Comment thread tsdb/db.go Outdated
Copy link
Copy Markdown
Member

@codesome codesome left a comment

Choose a reason for hiding this comment

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

We need to make changes to not do OOO compaction every minute (more in below comments).

Additionally, right now we can predict when in-order and out-of-order compactions happen (i.e. in between the block durations, so every odd hours for a 2h block duration). It would be nice to preserve this predictability. We can trigger the OOO compaction in the middle of two aligned OOOCompactInterval. i.e. if OOOCompactInterval was 2h, then OOO compactions would be attempted at odd hours (while even hours are the "aligned" OOOCompactInterval), which should be around the time in-order compaction happens. We can achieve this by calculating the time remaining until next trigger after every OOO compaction trigger and use time.After.

Comment thread tsdb/db.go Outdated
Comment thread tsdb/db.go Outdated
@MarkintoshZ MarkintoshZ requested a review from codesome January 29, 2023 23:13
Comment thread tsdb/db_test.go Outdated
Comment thread tsdb/db.go Outdated
Comment thread tsdb/db.go Outdated

// interval * 3 / 2 so that OOO compaction will happen around the same time as
// in-order compaction with default options
OOOScheduledCompact := time.NewTimer(db.opts.OutOfOrderCompactInterval * 3 / 2)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need to actually align the time w.r.t. the wall clock. So in this case, the math would be like this:

	OutOfOrderCompactInterval := 2 * time.Hour // The config.
	
	nowUnix := time.Now().Unix()
	oooCompactionIntvSec := int64(OutOfOrderCompactInterval / time.Second)
	// Aligned 'now'. In this example, an even hour.
	nextCompaction := (nowUnix / oooCompactionIntvSec) * oooCompactionIntvSec
	// Move the aligned 'now' to midway of the interval. In this example, the next odd hour.
	nextCompaction += oooCompactionIntvSec / 2
	if nextCompaction < nowUnix {
		nextCompaction += oooCompactionIntvSec
	}
	timeUntilNextCompaction := time.Duration(nextCompaction-nowUnix) * time.Second

	// oooScheduledCompact := time.NewTimer(timeUntilNextCompaction) // Use this now. Note the OOO->ooo.

	fmt.Println("Now", time.Now().UTC())
	fmt.Println("Waiting time", timeUntilNextCompaction)
	fmt.Println("Compaction will happen at", time.Now().Add(timeUntilNextCompaction).UTC())

The print statements and comments are for explaining. In the final code, you can say something like We align the compactions to happen with in-order compaction, which happens midway between aligned intervals of time.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Those make a lot of sense. When I implemented the change last time, I was actually quite confused about why we needed to align the compaction time if the alignment would change during the execution of the program (e.g. backoff from failing compaction). Now I understand what you mean by aligning with the compaction. Thank you for being extra patient with me!

Comment thread tsdb/db.go Outdated
Comment thread tsdb/db.go Outdated
Comment thread tsdb/db_test.go Outdated
@MarkintoshZ MarkintoshZ requested a review from codesome February 9, 2023 23:59
@MarkintoshZ
Copy link
Copy Markdown
Author

Since we do regular compaction and OOO compaction separately now, should we have two sets of compaction metric counters, one for regular and one for OOO?

@bwplotka
Copy link
Copy Markdown
Member

We definitely need a counter with some label "type" that is "head" or "ooo" perhaps (: @MarkintoshZ

Good work on this, happy to help going forward with @jesusvazquez sorry for lag!

@jesusvazquez
Copy link
Copy Markdown
Member

Since we do regular compaction and OOO compaction separately now, should we have two sets of compaction metric counters, one for regular and one for OOO?

Yes I think this a good call and also agree with Bartek's idea of using label values like head and ooo or head and ooohead.

@MarkintoshZ
Copy link
Copy Markdown
Author

I updated the db metrics to include both head and ooo completion counters. It's ready for review now @jesusvazquez :)

@roidelapluie
Copy link
Copy Markdown
Member

cc @jesusvazquez would you please take a look at this pull request again?

Thanks!

Copy link
Copy Markdown
Member

@ArthurSens ArthurSens left a comment

Choose a reason for hiding this comment

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

I've made some suggestions to how you're handling the new metrics.

Working with different labels, instead of different metrics, makes aggregation easier

Comment thread tsdb/db.go
Comment on lines +250 to +255
headCompactionsFailed prometheus.Counter
headCompactionsTriggered prometheus.Counter
headCompactionsSkipped prometheus.Counter
oooCompactionsFailed prometheus.Counter
oooCompactionsTriggered prometheus.Counter
oooCompactionsSkipped prometheus.Counter
Copy link
Copy Markdown
Member

@ArthurSens ArthurSens Mar 30, 2024

Choose a reason for hiding this comment

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

I wouldn't split the compaction metrics. Ideally, we keep the same metric but use different label values for each type of head.

Since we want new labels now, we would use prometheus.CounterVec instead of prometheus.Counter

Something like this:

- 	compactionsFailed    prometheus.Counter
-	compactionsTriggered prometheus.Counter
-	compactionsSkipped   prometheus.Counter
+	compactionsFailed    prometheus.CounterVec
+	compactionsTriggered prometheus.CounterVec
+	compactionsSkipped   prometheus.CounterVec

Comment thread tsdb/db.go
Comment on lines -285 to -287
m.compactionsTriggered = prometheus.NewCounter(prometheus.CounterOpts{
Name: "prometheus_tsdb_compactions_triggered_total",
Help: "Total number of triggered compactions for the partition.",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here we need to keep the metric you just deleted, but we'll use NewCounterVec instead. For example:

	m.compactionsTriggered = *prometheus.NewCounterVec(prometheus.CounterOpts{
		Name:        "prometheus_tsdb_head_compactions_triggered_total",
		Help:        "Total number of triggered compactions for the partition.",
	}, []string{"type"})

Comment thread tsdb/db.go
case <-oooScheduledCompact.C:
oooScheduledCompact.Reset(db.opts.OutOfOrderCompactInterval)

db.metrics.oooCompactionsTriggered.Inc()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When increasing the metric, you'll want:

			db.metrics.compactionsTriggered.WithLabelValues("ooohead").Inc()

or, when increasing the regular head metrics:

			db.metrics.compactionsTriggered.WithLabelValues("head").Inc()

Copy link
Copy Markdown
Member

@ArthurSens ArthurSens left a comment

Choose a reason for hiding this comment

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

Sorry for taking so long to review though, could we also ask you to resolve the conflicts? 😅

Comment thread tsdb/db.go
Comment on lines +989 to +990
// We align the compactions to happen with in-order compaction, which happens midway
// between aligned intervals of time.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// We align the compactions to happen with in-order compaction, which happens midway
// between aligned intervals of time.
// We align the out-of-order compactions to happen with in-order compaction, which happens midway
// between aligned intervals of time.

Copy link
Copy Markdown
Member

@jesusvazquez jesusvazquez left a comment

Choose a reason for hiding this comment

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

@MarkintoshZ this is close to completion, would you like to give it one last push?

@jesusvazquez
Copy link
Copy Markdown
Member

@MarkintoshZ gentle reminder about this PR! We'll be cutting Prometheus 3.0 major release in a month and we'd love to have this in if you are still up for it!

@bboreham
Copy link
Copy Markdown
Member

Hello from the bug-scrub! @MarkintoshZ do you think you will come back to this?

@MarkintoshZ
Copy link
Copy Markdown
Author

Yes, I will try to fix this PR and get it up to date by this weekend

@bboreham
Copy link
Copy Markdown
Member

bboreham commented Aug 26, 2025

Hello again from the bug-scrub! @MarkintoshZ we can hold this open since you indicated you would come back.
Please let us know if things have changed.

@poi1649 indicated they could pick it up.

@bboreham
Copy link
Copy Markdown
Member

bboreham commented Jan 6, 2026

Hello again from the bug-scrub!

@poi1649, did you get anywhere? You commented at #11834 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants