etcd-io/etcd
Write-ahead log (WAL)
Source: server/storage/wal/.
Purpose
The WAL is the durable log of every Raft entry, hard state, and CRC checkpoint. It is what makes etcd survive crashes: until an entry is fsynced into the WAL, the leader will not acknowledge it as committed. The WAL is also the first thing a member reads on startup to reconstruct its Raft state.
Directory layout
server/storage/wal/
├── wal.go # WAL struct, ReadAll, Save, releaseLockTo
├── encoder.go, decoder.go
├── repair.go # truncates partial last record
├── version.go # min-server / cluster compatibility
├── metrics.go
├── file_pipeline.go # pre-allocates next WAL segment
├── walpb/ # WAL record protobuf (Type, CRC, Data)
└── testing/, testdata/File format
A WAL is a sequence of fixed-name segment files (0000000000000000-0000000000000000.wal, ...) in the <data-dir>/member/wal/ directory. Each file is a stream of walpb.Record entries:
[ length | CRC | Type | Data ]Record types include:
| Type | Carried payload |
|---|---|
metadataType |
Cluster metadata (CIDr, member ID) |
entryType |
Raft log entry |
stateType |
Raft HardState |
crcType |
CRC checkpoint at start of file |
snapshotType |
Pointer to a snapshot (term/index) |
Segments are opened in append-only mode with a 64 MB pre-allocation (file_pipeline.go). When a segment fills up, the pipeline rotates to the next one already on disk.
Key abstractions
| Symbol | File | Description |
|---|---|---|
WAL |
server/storage/wal/wal.go |
Open log; offers Save, SaveSnapshot, ReadAll, Close |
Encoder / Decoder |
server/storage/wal/encoder.go, decoder.go |
Length-prefixed CRC-checked stream codec |
filePipeline |
server/storage/wal/file_pipeline.go |
Background pre-allocation of next segment |
Repair |
server/storage/wal/repair.go |
Trims a truncated last record on startup |
walpb.Record |
server/storage/wal/walpb/record.proto |
The on-disk record type |
How it works
graph LR
raft[raftNode] -->|Save(hardState, entries)| wal[WAL]
wal --> enc[Encoder]
enc --> file[(WAL segment file)]
file -->|fsync| disk[(disk)]
wal --> pipe[filePipeline]
pipe --> nextfile[(next segment)]
raftRestart[startup] -->|ReadAll| wal
wal --> dec[Decoder]
dec --> file- Save: the WAL appends one record per entry plus a record for the new hard state, computes the CRC into the running CRC accumulator, and
Sync()s the file. Segment rotation is automatic. - ReadAll: on startup, replays records into the in-memory list of Raft entries plus the latest hard state. Truncated trailing records get repaired by
repair.go. - Snapshot: when a snapshot is created, the WAL records a pointer to it; subsequent log files can be released up to that pointer.
Integration points
- Consumed by
server/etcdserver/raft.go's Ready loop. - Snapshot pointer file format is shared with
server/etcdserver/api/snap/. server/storage/storage.goexposes a unifiedStoragefacade that bundles WAL + snap + bolt.etcdutlandtools/etcd-dump-logs/parse the same format for forensics.
Entry points for modification
- New record type → add to
walpb/record.proto, runscripts/genproto.sh, add an Encoder/Decoder branch. - File-format version bumps →
version.goand the migration framework inserver/storage/schema/migration.go. - Performance:
file_pipeline.gois the place to tweak pre-allocation strategy; the project has resisted larger segments to keep recovery fast.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.