Step 1 of 3 · Reading · ~2 min
Key-Value Storage
String Commands
SET & GET — Key-Value Storage
This is the lesson where your project becomes a database. Everything before this chapter was protocol plumbing; SET and GET are the reason Redis exists — a fast, in-memory associative store.
The data structure
At its heart, Redis's keyspace is just a hash map from string keys to values:
That's genuinely most of the implementation. The interesting engineering is everywhere around this dict: expiry bookkeeping, type checking, concurrency, persistence — none of which you need yet. Resist the urge to over-engineer this now; a plain dict is the correct choice, and you'll layer a parallel expires: dict[str, float] on top of it in the Key Expiry chapter without needing to change this core structure.
Implementing SET
SET always succeeds (barring the conditional NX/XX flags you'll add two lessons from now) and always replies +OK\r\n.
Implementing GET
The critical detail: a missing key is not an error and not an empty string — it's RESP's null bulk string, $-1\r\n. This is the same null sentinel you learned about in the RESP Wire Format lesson, now put to its most common real use. Client libraries in every language map $-1\r\n to None/nil/null, so getting this wrong breaks every downstream consumer of your server, even though the bytes look almost like a valid reply.
Why "atomic" matters even here
Redis's single-threaded execution model means SET and GET are trivially atomic — no other command can interleave mid-operation. You get this for free as long as your command loop processes one request fully before reading the next; don't introduce background threads or async interleaving of command handling yet, or you'll need locks around store that Redis itself doesn't need.
Edge cases to check
- Empty value:
SET key ""should store an empty string, andGET keyshould return$0\r\n\r\n— not null. An empty string is a valid value, distinct from "no value." - Overwriting with GET in between: make sure your dict assignment doesn't accidentally append or merge —
SETalways fully replaces. - Keys are just strings: don't coerce numeric-looking keys or values into
int/float— Redis stores everything as byte strings internally; type coercion (for INCR, for example) happens at read-time in the command that needs it, not at storage time.
Once SET/GET work, every other command in this course — TTLs, conditional writes, counters — is really just "SET/GET plus one more rule," so get comfortable with this dict now.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…