Requirements to clarify: maintain exactly-once or at-least-once semantics, max allowed recovery time (RTO), state size and change rate, storage durability SLAs, and operational constraints (cloud object store vs local SSD).
Design choices
- Incremental checkpoints
- Store full base snapshot occasionally and write deltas (change-logs) between checkpoints. Use RocksDB-like local keyed state with SSTable-style checkpoints: persist only new SST files or WAL segments to remote storage. This reduces IO and upload time.
- Maintain compacted checkpoints via periodic full compaction to bound restore time and metadata complexity.
- Externalized durable checkpoints
- Write checkpoint data and a small immutable checkpoint-metadata file to durable object storage (S3/GCS). Keep metadata with: checkpoint id, offsets per source, operator parallelism mapping, and pointers to incremental segments.
- Use atomic publish: write tmp objects then rename/commit (or write manifest and atomically flip a pointer) so downstream restores see only complete checkpoints.
- Consistent snapshots across operators
- Use a barrier mechanism (Chandy–Lamport style): inject checkpoints barriers into source streams; operators snapshot state on barrier arrival and forward barrier only after local snapshot is durable. For asynchronous snapshots, block only the operator’s network partitioning briefly to ensure consistent global cut while avoiding full pipeline stop.
- For heterogeneous operators, capture in-flight buffers or use upstream flushing so offsets in metadata reflect exactly consumed records.
- Minimizing recovery time
- Use incremental restore: fetch base plus only needed deltas. Parallelize fetch and local materialization across tasks. Cache recent checkpoints on local SSD to avoid cold downloads.
- Maintain a small “latest-good” replicated replica on a warm standby cluster for ultra-low RTO for critical pipelines.
- Keep operator restore deterministic: replay only from source offsets recorded in checkpoint — allow consumers to resume from committed offsets.
- Preventing state corruption
- Write-ahead logs: persist incoming records (or state diffs) before applying mutating operations; during restore, replay WAL up to checkpoint point.
- Atomic commit for state and sink outputs: use two-phase commit for external side effects (idempotent writes, transaction coordinator, or exactly-once sink connectors). Mark checkpoint completion only after all operator states and sink transactions are committed.
- Validate checksums and versioning for checkpoint segments; reject partial or mismatched metadata during restore.
- Garbage collect old checkpoints only after newer stable checkpoints are fully committed and validated.
Trade-offs and notes
- More frequent incremental checkpoints lower data loss window but increase metadata and potential restore complexity. Compaction cadence balances snapshot size vs. CPU/IO.
- Asynchronous snapshotting with local RocksDB offers low pause times but requires robust upload/commit logic to avoid dangling partial state.
- For very large state, combine lightweight incremental checkpoints with source replay from committed offsets to reconstruct recent deltas, reducing storage cost at the expense of slightly longer recovery.
This design provides consistent global snapshots, efficient storage and transfer via incremental artifacts, fast parallel restores, and safeguards (WAL, atomic commits, checksums) to prevent corruption while enabling configurable RTO/throughput trade-offs.