Skip to content

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:

python

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

python

SET always succeeds (barring the conditional NX/XX flags you'll add two lessons from now) and always replies +OK\r\n.

Implementing GET

python

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, and GET key should 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 — SET always 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.

Up nextMultiple Keys & OverwriteString Commands

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…