RDB Snapshotting: The Time Machine
Imagine you are playing a video game and you reach a difficult boss level. What do you do? You save the game. If you die, you reload from that exact moment.
RDB (Redis Database) works exactly like a save game. It creates a point-in-time snapshot of your entire dataset at specified intervals. It’s the default persistence mode in Redis and is perfect for backups and disaster recovery.
But here is the million-dollar question: How does Redis copy gigabytes of data to disk without stopping the world?
If you have 10GB of data in memory, copying it to a file takes time. If Redis is single-threaded, does it freeze for 30 seconds while saving?
The answer lies in a clever operating system trick called fork() and Copy-On-Write (COW).
1. The Magic of fork() and COW
When you trigger a snapshot (either manually via BGSAVE or automatically via config), Redis does the following:
- Fork: The main Redis process (Parent) calls the
fork()system call to create a new process (Child). - Snapshot: The Child process sees an exact copy of the memory at the moment of the fork. It starts writing this data to a temporary RDB file.
- COW: The OS uses Copy-On-Write to make this efficient. Initially, Parent and Child share the same physical memory pages. No data is actually copied yet!
- Write: If the Parent receives a write command (e.g.,
SET user:1 "Alice"), the OS intercepts this. It duplicates only the specific memory page being modified. The Parent writes to the new page, while the Child keeps reading the old page.
Interactive: The COW Visualizer
See Copy-On-Write in action. Observe how memory usage only increases when you write data during a snapshot.
Parent Process (Main Redis)
2. Why This Matters: The Memory Spike Danger
Many developers treat Redis memory as simple RAM usage. But with RDB, you need to be careful.
If you have 16GB of RAM and your Redis dataset is 12GB, triggering a snapshot is dangerous.
- Best Case: No writes happen during the save. Memory usage stays at 12GB.
- Worst Case: You overwrite every single key during the save.
- The Child process holds the old 12GB.
- The Parent process allocates a new 12GB for the new data.
- Total Memory: 24GB.
- Result: The OS runs out of RAM and the OOM (Out Of Memory) Killer kills Redis.
[!WARNING] Always set
vm.overcommit_memory = 1in Linux. This tells the kernel “It’s okay to fork even if you don’t strictly have enough RAM to duplicate everything right now,” relying on COW to save the day.
3. How to Configure RDB
By default, Redis saves snapshots based on a time and write count rule.
# redis.conf
# Save after 3600 seconds (1 hour) if at least 1 key changed
save 3600 1
# Save after 300 seconds (5 mins) if at least 100 keys changed
save 300 100
# Save after 60 seconds if at least 10000 keys changed
save 60 10000
Triggering Snapshots in Code
Sometimes you need to trigger a backup programmatically before a risky migration.
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
// Trigger BGSAVE
status := rdb.BgSave(ctx)
if err := status.Err(); err != nil {
panic(err)
}
fmt.Println("Snapshot started:", status.Val())
// In production, you might monitor 'rdb_last_bgsave_status' in INFO
}
4. RDB Pros and Cons
| Feature | Verdict | Why? |
|---|---|---|
| Performance | ✅ Excellent | Parent process does almost no IO work. |
| Backups | ✅ Excellent | Single compact file (dump.rdb) is easy to transfer to S3/FTP. |
| Startup Speed | ✅ Fast | Loading RDB is much faster than replaying AOF logs. |
| Data Safety | ❌ Risk | If Redis crashes, you lose all data since the last snapshot (e.g., last 5 mins). |
| Memory | ⚠️ Heavy | Can potentially double memory usage during heavy write loads. |
5. Next Steps
RDB is great for backups, but what if you cannot afford to lose any data? In the next chapter, we will look at AOF (Append Only File).