-
Notifications
You must be signed in to change notification settings - Fork 529
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 experimental support to force compact TSDB head when ingester in-memory series are above a threshold #5371
Add experimental support to force compact TSDB head when ingester in-memory series are above a threshold #5371
Conversation
0184c4e
to
953dce6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any major blockers in the PR, changes make sense to me, and it's worth giving it a try.
return u.db.CompactOOOHead() | ||
} | ||
|
||
// nextForcedHeadCompactionRange computes the next TSDB head range to compact when a forced compaction | ||
// is triggered. If the returned isValid is false, then the returned range should not be compacted. | ||
func nextForcedHeadCompactionRange(blockDuration, headMinTime, headMaxTime, forcedMaxTime int64) (minTime, maxTime int64, isValid, isLast bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: isLast bool
looks like unnecessary optimization to save one call to the function, and it can be wrong (if forcedMaxTime is aligned on block boundary). I'd drop it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not an optimization. The problem is that when compacting a partial head (so for the case of this PR) without that flag we may end up in a infinite loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since no pushes are allowed that would modify maxTime, why would we end up in an infinite loop? Are you talking about the case when minTime == maxTime?
953dce6
to
692dc45
Compare
No good. Just got a panic in CI. Will investigate:
|
Another panic observed locally, while investigating the previous one:
|
I did some investigation and this panic shouldn't happen in the real world. It's triggered by an edge case in the unit test, that should be fixed by this: prometheus/prometheus#12500
This should also be fixed by prometheus/prometheus#12500 and, again, in practice shouldn't happen in the real world, but about this panic I want to do more investigation tomorrow to be more confident. |
3a56d65
to
0fea21d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I've left some minor comments, but nothing blocking as far as I can see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unblocking with nits
pkg/ingester/ingester.go
Outdated
estimatedSeriesReduction := db.Head().NumSeries() - uint64(db.activeSeries.Active()) | ||
|
||
// Skip if the estimated series reduction is too low (there would be no big benefit). | ||
if float64(estimatedSeriesReduction)/float64(numInitialMemorySeries)*100 < float64(i.cfg.BlocksStorageConfig.TSDB.EarlyHeadCompactionMinEstimatedSeriesReductionPercentage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we do this?
if float64(estimatedSeriesReduction)/float64(numInitialMemorySeries)*100 < float64(i.cfg.BlocksStorageConfig.TSDB.EarlyHeadCompactionMinEstimatedSeriesReductionPercentage) { | |
if float64(estimatedSeriesReduction)/float64(db.Head().NumSeries())*100 < float64(i.cfg.BlocksStorageConfig.TSDB.EarlyHeadCompactionMinEstimatedSeriesReductionPercentage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea of this PR is to check it against the total number of series in the ingester, and not the per-tenant TSDB. Let's say you configure the percentage to 10%, a tenant has 100 series, and 20 are inactive. If you check against the per-tenant TSDB, it will trigger the compaction, but in practice it will not move a needle. Comparing against the total number of series in the ingester allow us to only trigger the early compaction in case there are big opportunities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then this setting will be quite useless in multi-tenant environments. If you have 10 tenants each one saving 50% of their series, you could save a total of 50% by compacting them, but with current logic you won't trigger the compaction because each tenant will save only 5% of the total. Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The math is correct but I think it's all about the percentage you configure. Maybe in multi-tenant environments it makes sense a lower %. I think this is something we can refine over time, but I definitely want to keep a way to avoid compacting a TSDB when the overall impact is negligible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that having it this way will require tons of tuning, because the setting doesn't relate to the final effect. I have an ingester with a number of in-memory series, and I want to make sure that we compact heads when I can save a given amount of memory. I shouldn't need to update the percentage based on the number of tenants I have in order to achieve that.
IMO it's counter-intuitive.
OTOH, what's the problem about compacting 10 smaller Heads vs compacting one bigger?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline. I pushed a commit to include Oleg's suggestion, but slightly modified to also compact all TSDBs with an high number of inactive series (even if below the configured %).
There's no strong consensus between the two of us on what's the right way to decide which TSDBs to compact. The gist is that is difficult to have good arguments because we'll learn it the hard way (running it for some time).
…memory series are above a threshold Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
…tedBeforeForcedCompaction Signed-off-by: Marco Pracucci <marco@pracucci.com>
….yaml Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
…HeadUpUntilNowMinusActiveSeriesMetricsIdleTimeout from subtests to code blocks Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
30db2d1
to
6ad09d2
Compare
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
…ke it testable Signed-off-by: Marco Pracucci <marco@pracucci.com>
…locksHonoringBlockRangePeriod Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
What this PR does
In this PR I propose to add the experimental support to force compact the per-tenant TSDB Head when the ingester in-memory series are above a configured threshold and the ingester estimates that compacting the head up until "now - active series idle timeout" can significantly reduce the number of in-memory series.
How it works:
-blocks-storage.tsdb.head-compaction-interval
.Notes about forced compaction:
-blocks-storage.tsdb.head-compaction-interval
-blocks-storage.tsdb.forced-head-compaction-min-estimated-series-reduction-percentage
Notes about TSDB:
Which issue(s) this PR fixes or relates to
N/A
Checklist
CHANGELOG.md
updated - the order of entries should be[CHANGE]
,[FEATURE]
,[ENHANCEMENT]
,[BUGFIX]