Build Redis (10 scenes)
Scene 04 · Persistence — fork, CoW, and the 1-second window
RDB snapshots via fork+CoW, AOF fsync policies, and why default Redis can lose ~1s of writes on crash.
Previously

You've seen what's in RAM and how it's encoded. None of it survives a crash on its own — persistence is how the live keyspace becomes bytes on disk.

Scene 04
Persistence — fork, CoW, and the 1-second window
Diagram
On the left, the live keyspace held in RAM, drawn as a page grid. RDB forks a child process — shown as a snapshot copy on the right — that writes the dump while the parent keeps serving; pages mutated during the snapshot get copied (CoW) and the memory gauge climbs. At the bottom, the AOF buffer accumulates writes and an fsync arrow drains it to disk on the policy you pick (always / everysec / no).
fork pause: idle4KB pagesRedis parentserving clientsPAGE TABLE · regular pages (4KB)shared (CoW)copieddirtywritesRSS240 MBAOF TAIL · buffer → fsync → diskappendfsynceverysecfsync ≤ 1sLost writes0none
fsync once per second · THP OFF (4 KB CoW unit)
Watch writes land on the AOF tail (amber = buffered) and flip emerald when the everysec fsync fires. After a few seconds, BGSAVE forks a child — pages start flipping orange one by one as the parent keeps writing during the snapshot.
Implementation
Server.bgsave()
fork a child; parent keeps serving on copy-on-write pages
1def bgsave():
2 pid = fork()
3 if pid == 0:
4 # child: frozen view of memory at fork time
5 writeRDB(snapshot=heap_snapshot())
6 exit(0)
7 # parent returns immediately; serves clients
8 # while pages diverge via CoW on each write.
9 return pid
Server.handleWrite(cmd)
mutate memory, append to AOF buffer, reply OK
1def handleWrite(cmd):
2 apply(cmd, db) # in-memory mutation
3 aof_buf.append(cmd) # OS page-cache write
4 if cfg.appendfsync == 'always':
5 fsync(aof_fd) # block until on disk
6 reply_ok(client) # ack returns to caller
aofFlushBackground() # everysec
background thread fsyncs the AOF once per second
1def aofFlushBackground():
2 last_fsync = now()
3 while running:
4 if now() - last_fsync >= 1.0:
5 fsync(aof_fd)
6 last_fsync = now()
7 sleep(0.1)
kernel.pageWrite(page)
first parent write to a shared page triggers the copy
1def pageWrite(page):
2 if page.shared:
3 new = copy_page(page) # 4 KB, or 2 MB under THP
4 page.shared = False
5 mark_copied(page, new)
6 write_into(page)