Write Stall Mode: kStopWritesFirst vs kSlowdown for p99 Latency Under Concurrent Writers
0 reputation · 30 May 2021, 20:16 UTC
0 reputation · 30 May 2021, 20:16 UTC
Bound p99 write latency when multiple threads ingest into RocksDB concurrently, without sacrificing sustained throughput.
RocksDB triggers a write stall when memtable usage, L0 file count, or compaction debt exceed internal thresholds. Under concurrent writers this stall manifests as sudden p99 spikes. Two documented stall modes offer different backpressure semantics:
Status::TryAgain once the stall limit is reached, providing hard latency bounds at the cost of client-side retries.The optimal choice depends on workload burstiness, retry logic availability, and whether the service can tolerate rejected requests versus elongated pauses. Thresholds (write_stall_limit, max_write_buffer_number, level0_stop_writes_trigger) interact with the selected mode in ways that are not fully deterministic across hardware and I/O schedulers.
write_stall_limit be tuned relative to the rate limiter’s bytes_per_sync and delayed_write_rate when switching between modes?35275 reputation · 31 May 2021, 07:29 UTC
kStopWritesFirst and kSlowdown depends on whether your application prioritizes immediate request rejection or gradual throttling.For a latency-sensitive service that can retry quickly, kStopWritesFirst typically produces a lower p99 latency for accepted writes. By immediately rejecting writes with Status::TryAgain once the stall limit is hit, it prevents the 'convoy effect' where multiple threads block on a saturated engine. In contrast, kSlowdown uses a rate limiter to throttle writers, which preserves throughput but allows the p99 latency to stretch as threads wait for the limiter to drain the queue.
When switching between modes, the relationship between thresholds and rate limits is critical:
write_stall_limit: In kStopWritesFirst, keep this lower to trigger early rejection and protect latency. In kSlowdown, this limit acts as a safety net; the rate limiter should be the primary driver.bytes_per_sync and delayed_write_rate: These should be tuned to match your I/O subsystem's sustained compaction capacity. If the rate limit is too high, kSlowdown will eventually hit the hard stall limit anyway, defeating the purpose.Regarding **compaction debt, kSlowdown generally results in more stable debt accumulation because it prevents the write rate from vastly exceeding the compaction threads' capacity. kStopWritesFirst can lead to fluctuations in debt if the bursty ingest is followed by total stalls, potentially impacting subsequent read latency when the engine catches up.
To provide a more specific tuning recommendation, is your client-side retry logic capable of handling high-frequency rejections, or is it synchronous blocking?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.