/src/rocksdb/db/periodic_compaction_phaser.h
Line | Count | Source |
1 | | // Copyright (c) Meta Platforms, Inc. and affiliates. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | |
6 | | #pragma once |
7 | | |
8 | | #include <cstdint> |
9 | | #include <string> |
10 | | |
11 | | #include "rocksdb/rocksdb_namespace.h" |
12 | | |
13 | | namespace ROCKSDB_NAMESPACE { |
14 | | |
15 | | // Parameters controlling randomized-but-stable phasing of periodic |
16 | | // (time-based) compaction, derived per Version from |
17 | | // DBOptions::periodic_compaction_phase_recovery_percent together with the DB ID |
18 | | // and column-family id. recovery_percent == 0 disables phasing (exact legacy |
19 | | // behavior). |
20 | | struct PeriodicCompactionPhaseParams { |
21 | | // Stable per-(DB, CF) hash seeding the preferred phase. |
22 | | uint64_t seed_hash = 0; |
23 | | // Unix time (seconds) at which phasing took effect for this DB (DB::Open, or |
24 | | // the last relevant SetDBOptions change). Used to spread out the initial |
25 | | // catch-up burst. |
26 | | uint64_t anchor_time = 0; |
27 | | // Percent [0, 100] of the phase gap closed per trigger; 0 disables phasing. |
28 | | int recovery_percent = 0; |
29 | | }; |
30 | | |
31 | | // De-herds periodic (time-based) compaction across a fleet: gives each (DB, CF) |
32 | | // a stable "preferred phase" within periodic_compaction_seconds and steers |
33 | | // compactions toward it, never past the deadline (enabled by |
34 | | // DBOptions::periodic_compaction_phase_recovery_percent). The DB-level base |
35 | | // phase is derived from the DB ID -- stable across re-open and physical |
36 | | // cloning/migration but distinct across DBs -- and each column family is spread |
37 | | // around it by cf id. This owns the DB-level recovery percent and the phasing |
38 | | // anchor; the per-file trigger math and phase derivation are stateless static |
39 | | // helpers. Lives on VersionSet, which caches the resulting per-CF params on |
40 | | // each Version. |
41 | | class PeriodicCompactionPhaser { |
42 | | public: |
43 | | // db_id is referenced live (it is populated after construction, during |
44 | | // DB::Open, and is read lazily) and must outlive this phaser -- it is owned |
45 | | // by the same VersionSet. |
46 | 44.8k | explicit PeriodicCompactionPhaser(const std::string& db_id) : db_id_(db_id) {} |
47 | | |
48 | | // Apply the (mutable) recovery percent. Returns true if it changed -- in |
49 | | // which case the caller should Reanchor() and refresh cached params. Does not |
50 | | // itself move the anchor. |
51 | | // |
52 | | // A setting of 25 to 33 will set this phaser to "stun" |
53 | | bool SetConfig(int recovery_percent); |
54 | | |
55 | | // Move the phasing anchor to `now` (unix seconds). |
56 | 0 | void Reanchor(uint64_t now) { anchor_time_ = now; } |
57 | | |
58 | 0 | int recovery_percent() const { return recovery_percent_; } |
59 | | |
60 | | // Phasing params for a column family (by id): the DB base phase (hashed from |
61 | | // the DB ID) spread by cf_id (golden ratio), plus the current anchor and |
62 | | // recovery percent. Returns disabled params when phasing is off. |
63 | | PeriodicCompactionPhaseParams ParamsForCf(uint32_t cf_id) const; |
64 | | |
65 | | // --- Stateless helpers (static; unit-tested directly) --- |
66 | | |
67 | | // Wall-clock time (unix seconds) at which a file with the given modification |
68 | | // time becomes eligible for periodic compaction under `params`, NOT |
69 | | // accounting for the offpeak pull. When params.recovery_percent == 0 (phasing |
70 | | // disabled) this is file_modification_time + periodic_compaction_seconds |
71 | | // (classic behavior); otherwise it is steered earlier toward the preferred |
72 | | // phase. It is never before params.anchor_time and, unless the file was |
73 | | // already past due then, never later than the classic deadline. Catch-up |
74 | | // after anchor_time is spread out so that many DBs anchoring at once (e.g. |
75 | | // phasing enabled across a fleet) do not concentrate periodic compactions |
76 | | // shortly after it. |
77 | | static uint64_t TriggerTime(uint64_t file_modification_time, |
78 | | uint64_t periodic_compaction_seconds, |
79 | | const PeriodicCompactionPhaseParams& params); |
80 | | |
81 | | // Longest periodic_compaction_seconds (~68 years) to which phasing applies, |
82 | | // to keep the arithmetic simple and direct. |
83 | | static constexpr uint64_t kMaxPhasedPeriod = uint64_t{1} << 31; |
84 | | |
85 | | // Spreads a DB's column families quasi-uniformly around a DB-level base phase |
86 | | // via the golden-ratio additive (Weyl/Kronecker) recurrence: cf phase == |
87 | | // db_base_phase + cf_id * (phi conjugate), all in fixed point (fraction * |
88 | | // 2^64) so the mod-1 wrap is the natural uint64 overflow. Low-discrepancy for |
89 | | // any number of CFs. |
90 | | static uint64_t CfPhaseSeedHash(uint64_t db_base_phase, uint32_t cf_id); |
91 | | |
92 | | private: |
93 | | const std::string& db_id_; |
94 | | int recovery_percent_ = 0; |
95 | | // Unix time (seconds) at which phasing took effect for this DB (construction |
96 | | // or last relevant SetDBOptions change); spreads the initial catch-up burst. |
97 | | uint64_t anchor_time_ = 0; |
98 | | }; |
99 | | |
100 | | } // namespace ROCKSDB_NAMESPACE |