Investigate CPU-efficient compression for raft snapshot writes.
- Dominant language
- Go
- Stars
- 30.1k
- Forks
- 4.6k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 43
Description
## Background
This is a follow up to several incidents where the failure described in #9609 was the root cause.
This issue is a general performance improvement that could be low-hanging fruit to reduce Disk IO during snapshotting. This could be a significant performance enhancement in general for many write-heavy work loads, but if successful would provide clusters at risk of the replication failure described in the other issue additional headroom.
## Proposal
When there is a large amount of data stored in the state store, raft snapshots serialize and write it out to disk for every 16k updates. When the write rate is high this snapshotting can often occur frequently - perhaps every minute.
Often these workloads are IO bound not CPU bound, so using an efficient compression algorithm - especially one like Snappy designed specifically to trade minimal CPU for significant IO reductions - seems like it could be a relatively easy win.
This would likely need to be done in the raft lib and enabled as an option. The file snapshot is https://github.com/hashicorp/raft/blob/e3c5b666287bb8dfe4131ae8759eacc75bbb39c0/file_snapshot.go. It would be possible for Consul to have its own implementation of `FileSnapshot` but if this optimization works well there's not real reason we shouldn't have it available for other users of the raft library.
The fact the snapshot is compressed (and with which algorithm) should probably be stored in the metadata file and read during restore so the appropriate decompression is used. This allows a single implementation to correctly handle a mixture of compression configurations that could be present before and after changing this config or after an older snapshot is restored (from a disk backup not an external snapshot since that has a separate API).
Note that we already (in Consul IIRC) gzip the external cluster snapshots users can make, this is specifically for the internal ones raft persists automatically which are not currently compressed.
I suggest since this is meant to be a "quick win" rather than a comprehensive analysis, time boxing and investigation on this to a couple of days, work with a single dev-mode consul agent and a script that writes a fixed-size (1M) set of large KVs as quickly as possible and observe snapshot timing (from logs or setup a local prometheus or similar). The fixed size means that eventualy every snapshot should be the same size and the time taken to write this out can be compared before and after compression.
With baselines stats, try wrapping the compression lib into the `FileSnapshot` and seeing how write times are affected.
If the results show enough gain, then we can do the pluming for config, detecting the right type on read etc. and then plumbing the config into Consul too.
Contributor guide
Assessment
This issue has not been assessed yet.