Skip to content

tsdb: drop deleted series from the WAL sooner#12297

Merged
bboreham merged 3 commits into
prometheus:mainfrom
bboreham:drop-deleted-series-sooner
May 1, 2023
Merged

tsdb: drop deleted series from the WAL sooner#12297
bboreham merged 3 commits into
prometheus:mainfrom
bboreham:drop-deleted-series-sooner

Conversation

@bboreham

Copy link
Copy Markdown
Member

head.deleted holds the WAL segment in use at the time each series was removed from the head. At the end of truncateWAL() we will delete all segments up to last, so we can drop any series that were last seen in a segment at or before that point.

Also, we can drop series from the deleted map up to last, since all those files are now deleted.

Improves #12286, but not a full fix.
Related to #12288.

Illustrated is a Prometheus TSDB that has been collecting data since 10:00 UTC.
WAL segments are named A, B, C, ...

Consider a series foo which received a few samples at 10:15, then stopped.
The samples for series foo are in WAL segment C.

           10:00        12:00
Head       ┌───────────────────┐
           └───────────────────┘
WAL        A- B- C- D- E-- F- G-

At approx 13:00, head compaction runs. A block is created from 10-12, and
that data is dropped from the head. Series foo is garbage-collected, but
the head notes in its 'deleted' map that it might be needed until WAL segment G has
been dropped.

A WAL checkpoint is created from the first two thirds of the segments, A-D.
WAL segments A-D are removed from disk.

At approx 15:00, head compaction runs again.

           10:00        12:00        14:00
Head                    ┌───────────────────┐
                        └───────────────────┘
Blocks     ┌────────────┐
           └────────────┘
WAL                    E-- F- G- H I- J-- K-
Checkpoint            X

A WAL checkpoint is created covering segments E-H.
Now series foo is dropped from the checkpoint, since the 'deleted' map says we need it until G, but we will be deleting G.
The 'deleted' map is cleaned of any series needed until segment 'H'.

Removing the series at 15:00 is an improvement on retaining it until 19:00 per the original issue #12286.

Let's also consider the case that was a problem for #12288: the samples are in segment J and we are truncating A-H:

           10:00        11:00        12:00        13:00
Head       ┌───────────────────────────────────────┐
           └───────────────────────────────────────┘
WAL        A B C D E F G H- I-- J--- K--- L--- M---

The deleted entry for samples would be J or later, so the series would be retained in the checkpoint, and in the deleted map.

`head.deleted` holds the WAL segment in use at the time each series was
removed from the head. At the end of `truncateWAL()` we will delete
all segments up to `last`, so we can drop any series that were last seen
in a segment at or before that point.

Signed-off-by: Bryan Boreham <[email protected]>
@bboreham
bboreham requested a review from codesome as a code owner April 26, 2023 17:33
@cstyan

cstyan commented Apr 26, 2023

Copy link
Copy Markdown
Member

Thanks for the detailed explanation in this and your other PR, I think I understand the original behaviour now. So this is my understanding;

In gc we currently use wal.Segments to get last which is the current last segment. The one we're actively writing to. This is the last possible segment any series currently in Head could have samples in, but it doesn't necessarily have samples up until that segment. We use that value of last as the value we store into the h.deleted map.

So in this PR, the way we're deleting is the earliest/safest we could without any additional logic, but it's still not the earliest possible.

Unless I am misunderstanding, as a safer alternative to your original PR, we could add code to track the last segment for which a sample was written to the WAL. At the time we truncate the WAL, if we're truncating up to segment id > series last segment id then we can delete the series completely (as in not write it's series record to the checkpoint). I've hacked that together here: d07b70a

@bboreham bboreham changed the title tsdb: drop deleted series sooner tsdb: drop deleted series from the WAL sooner Apr 27, 2023
Comment thread tsdb/head.go Outdated
`head.deleted` holds the WAL segment in use at the time each series was
removed from the head. At the end of `truncateWAL()` we will delete
all segments up to `last`, so we can drop any series that were last seen
in a segment at or before that point.

Same change as in `tsdb/head.go`.

Signed-off-by: Bryan Boreham <[email protected]>
@bboreham

Copy link
Copy Markdown
Member Author

Thanks to @rfratto for pointing out very similar code is in the agent package. It actually had half of this fix applied already, looking at the segment number in deleted.

I have applied the same change to use last instead of first as the comparator, and also fixed a typo in my previous commit.
Recommend squashing these commits if this PR is merged.

@bboreham

Copy link
Copy Markdown
Member Author

/prombench main

@prombot

prombot commented Apr 29, 2023

Copy link
Copy Markdown
Contributor

⏱️ Welcome to Prometheus Benchmarking Tool. ⏱️

Compared versions: PR-12297 and main

After successful deployment, the benchmarking metrics can be viewed at:

Other Commands:
To stop benchmark: /prombench cancel
To restart benchmark: /prombench restart main

@bboreham

bboreham commented Apr 30, 2023

Copy link
Copy Markdown
Member Author

I restarted the prombench Prometheus pods so they would reload the WAL.

Head series peak is much reduced, as hoped - 9.56M instead of 17.68M:
image

RSS peak is down to 28.6GB from 32.6GB:
image

WAL checkpoint replay time came down from 60 seconds to 26 seconds.

Dashboard link

@bboreham

Copy link
Copy Markdown
Member Author

/prombench cancel

Left it running a few more hours to see if the memory would equalise, but the one with smaller WAL checkpoint is consistently smaller.

@prombot

prombot commented Apr 30, 2023

Copy link
Copy Markdown
Contributor

Benchmark cancel is in progress.

@SuperQ
SuperQ self-requested a review May 1, 2023 14:25

@SuperQ SuperQ left a comment

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.

Very nice

@Shahard2

Shahard2 commented Aug 3, 2023

Copy link
Copy Markdown

It didn't help our WAL loading issues... still OOM's non stop

rfratto added a commit to rfratto/agent that referenced this pull request Sep 1, 2023
This change causes deleted series to be deleted earlier based on the
last segment involved in the checkpoint rather than the first segment
involved in the checkpoint.

This will then cause the next truncate to be more aggressive with
dropped series, which should help free memory associated with deleted
series in remote_write sooner.

Mirrors prometheus/prometheus#12297 from @bboreham.
tpaschalis pushed a commit to grafana/agent that referenced this pull request Sep 4, 2023
This change causes deleted series to be deleted earlier based on the
last segment involved in the checkpoint rather than the first segment
involved in the checkpoint.

This will then cause the next truncate to be more aggressive with
dropped series, which should help free memory associated with deleted
series in remote_write sooner.

Mirrors prometheus/prometheus#12297 from @bboreham.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants