mirror of
https://github.com/neondatabase/neon.git
synced 2025-12-22 21:59:59 +00:00
N.B: No-op for the neon-env. ## Problem We added a per-timeline disk utilization protection circuit breaker, which will stop the safekeeper from accepting more WAL writes if the disk utilization by the timeline has exceeded a configured limit. We mainly designed the mechanism as a guard against WAL upload/backup bugs, and we assumed that as long as WAL uploads are proceeding as normal we will not run into disk pressure. This turned out to be not true. In one of our load tests where we have 500 PGs ingesting data at the same time, safekeeper disk utilization started to creep up even though WAL uploads were completely normal (we likely just maxed out our S3 upload bandwidth from the single SK). This means the per-timeline disk utilization protection won't be enough if too many timelines are ingesting data at the same time. ## Summary of changes Added a global disk utilization protection circuit breaker which will stop a safekeeper from accepting more WAL writes if the total disk usage on the safekeeper (across all tenants) exceeds a limit. We implemented this circuit breaker through two parts: 1. A "global disk usage watcher" background task that runs at a configured interval (default every minute) to see how much disk space is being used in the safekeeper's filesystem. This background task also performs the check against the limit and publishes the result to a global atomic boolean flag. 2. The `hadron_check_disk_usage()` routine (in `timeline.rs`) now also checks this global boolean flag published in the step above, and fails the `WalAcceptor` (triggers the circuit breaker) if the flag was raised. The disk usage limit is disabled by default. It can be tuned with the `--max-global-disk-usage-ratio` CLI arg. ## How is this tested? Added integration test `test_wal_acceptor.py::test_global_disk_usage_limit`. Also noticed that I haven't been using the `wait_until(f)` test function correctly (the `f` passed in is supposed to raise an exception if the condition is not met, instead of returning `False`...). Fixed it in both circuit breaker tests. --------- Co-authored-by: William Huang <william.huang@databricks.com>
92 lines
2.4 KiB
TOML
92 lines
2.4 KiB
TOML
[package]
|
|
name = "safekeeper"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
license.workspace = true
|
|
|
|
[features]
|
|
default = []
|
|
# Enables test-only APIs, incuding failpoints. In particular, enables the `fail_point!` macro,
|
|
# which adds some runtime cost to run tests on outage conditions
|
|
testing = ["fail/failpoints"]
|
|
benchmarking = []
|
|
|
|
[dependencies]
|
|
async-stream.workspace = true
|
|
anyhow.workspace = true
|
|
byteorder.workspace = true
|
|
bytes.workspace = true
|
|
camino.workspace = true
|
|
camino-tempfile.workspace = true
|
|
chrono.workspace = true
|
|
clap = { workspace = true, features = ["derive"] }
|
|
crc32c.workspace = true
|
|
fail.workspace = true
|
|
hex.workspace = true
|
|
humantime.workspace = true
|
|
http.workspace = true
|
|
hyper0.workspace = true
|
|
itertools.workspace = true
|
|
jsonwebtoken.workspace = true
|
|
futures.workspace = true
|
|
once_cell.workspace = true
|
|
parking_lot.workspace = true
|
|
pageserver_api.workspace = true
|
|
postgres-protocol.workspace = true
|
|
pprof.workspace = true
|
|
rand.workspace = true
|
|
regex.workspace = true
|
|
reqwest = { workspace = true, features = ["json"] }
|
|
rustls.workspace = true
|
|
scopeguard.workspace = true
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
smallvec.workspace = true
|
|
strum.workspace = true
|
|
strum_macros.workspace = true
|
|
thiserror.workspace = true
|
|
tikv-jemallocator.workspace = true
|
|
tokio = { workspace = true, features = ["fs"] }
|
|
tokio-io-timeout.workspace = true
|
|
tokio-postgres.workspace = true
|
|
tokio-rustls.workspace = true
|
|
tokio-tar.workspace = true
|
|
tokio-util = { workspace = true }
|
|
tracing.workspace = true
|
|
url.workspace = true
|
|
metrics.workspace = true
|
|
pem.workspace = true
|
|
postgres_backend.workspace = true
|
|
postgres_ffi.workspace = true
|
|
postgres_ffi_types.workspace = true
|
|
postgres_versioninfo.workspace = true
|
|
pq_proto.workspace = true
|
|
remote_storage.workspace = true
|
|
safekeeper_api.workspace = true
|
|
safekeeper_client.workspace = true
|
|
sha2.workspace = true
|
|
sd-notify.workspace = true
|
|
storage_broker.workspace = true
|
|
tokio-stream.workspace = true
|
|
http-utils.workspace = true
|
|
utils.workspace = true
|
|
wal_decoder.workspace = true
|
|
env_logger.workspace = true
|
|
nix.workspace = true
|
|
|
|
workspace_hack.workspace = true
|
|
|
|
[dev-dependencies]
|
|
criterion.workspace = true
|
|
itertools.workspace = true
|
|
walproposer.workspace = true
|
|
rand.workspace = true
|
|
desim.workspace = true
|
|
tracing.workspace = true
|
|
tracing-subscriber = { workspace = true, features = ["json"] }
|
|
|
|
[[bench]]
|
|
name = "receive_wal"
|
|
harness = false
|
|
required-features = ["benchmarking"]
|