"It all started in 2004 when Amazon was running Oracle's enterprise edition with clustering and replication," Werner Vogels, Amazon's CTO, recalled in 2017. The database could not "sustain the availability, scalability and performance needs" of the business, and "a deep dive on how we were using our existing databases revealed that they were frequently not used for their relational capabilities": "About 70 percent of operations were of the key-value kind, where only a primary key was used and a single row would be returned." That was "the genesis of the Amazon Dynamo database", published in 2007; Riak, in the key-value cell of p. 342, is one of its clones (p. 411), and Amazon's DynamoDB followed in 2012.
A database with no queries: key-value stores and Redis
After this lesson you will explain why a database that answers only "what is under this key?" exists, say what Redis adds to that idea and what it is not, explain why one thread makes every command atomic and still fast, and choose the right one of the seven data types for a need.
"Every 1/10 second delay resulted in 1% loss of sales." That is what the slide on p. 343 prints next to Amazon's name; on the same slide Google loses 20 % of its traffic for half a second of delay. Speed is money.
In 2009 Salvatore Sanfilippo was trying to make LLOOGG, the real-time web-log analyser of his Italian startup, scale, and traditional database systems could not keep up with some of its workloads. He wrote his own database and gave up almost everything a relational one offers: no SQL, no joins, no secondary indexes, everything kept in memory, and a single thread that runs one command at a time. He called it Redis.
Two of those choices sound backwards. How can a database that answers only one question — "what is stored under this key?" — be the fix when a relational database is too slow? And how can a server that uses one CPU core, one command at a time, need no locks at all and still keep up? By the end of the lesson you will answer both in the slides' own words.
One key, one value, one step
The lecture opens on the map of p. 342, "Overview – NoSQL Family": "Data stored in 4 types: Document, Graph, Key-value, Wide-column", with Redis, Amazon DynamoDB, Aerospike and Riak in the key-value cell (the four families are in lesson 5). Key-value is the plainest of the four, and p. 343, "Why is performance important?", says why anyone wants it: speed. Besides Amazon's 1 % of sales and Google's "20% drop in traffic", it reports that for a "1-second delay in page-load time" an "Industrial Group" counted "11% fewer page views", "16% decrease in customer satisfaction" and "7% loss in conversions".
Take the slide's own example, the blog database of p. 346 (Fig. 1). To show the page of blog post 101 you need its text from the blog table, its author's name from users and its category from category: three tables, tied by foreign keys. A key-value store keeps the whole page — text, author, category — as one value under one key, post:101, and hands it back in one step.
Key-value store — a database that stores every value under a unique key and reaches it only through that key: "(Business) Key -> Value" (p. 345). Its whole interface is: put a value under a key, get the value of a key, delete a key. The value is opaque: the store never looks inside it.
The examples of p. 345 are keys that businesses already have: "(twitter.com) tweet id -> information about tweet", "(kayak.com) Flight number -> information about flight", an account number at a bank, an item number at Amazon. Most of what a site is asked starts from one of them, hence the slide's last line: "Search by ID is usually built on top of a key-value store". In Python terms the store is a dict: d[key] = value, d[key], del d[key] — and no loop over the values.
Page 346 asks the obvious question, "Isn't that just a database?", and lists what a relational database is: "Queried using SQL", "Key-based", "Foreign keys", "Indexes", "Joins". Read the list as two columns: a relational database has all five, a key-value store keeps only one — key-based. Keys exist in both, but they play different roles. In the relational blog the primary and foreign keys connect the tables, indexes let SQL search by any column — the slide's query, SELECT user_id from users WHERE username = "jbellis", finds a user by name, not by key — and joins put the page back together. The course notes say it in one line: in a key-value store "keys are just used to retrieve a specific value, unlike relational databases where primary and foreign keys are means to do searches and mapping between tables".
Before: the relational way (p. 346)
After: the key-value way
GET post:101. A question about what is inside the values, such as all the posts of jbellis, has no way in.So the key-value store gives up a lot: no query on what is inside the values, no join, no secondary index, no schema to check. What it buys with that is cost. A lookup by key in a hash table takes one step whatever the number of keys, and nothing has to be parsed, planned or assembled. The race below puts numbers on it.
One step in memory is the whole point. A relational lookup, however well indexed, climbs a tree whose height grows with the data and, on disk, pays a seek at every level; a join pays it once per table.
A key-value store answers one question — what is under this key? — and gives up every other question to answer that one in a single step.
There is a second gift (background, not on these slides). Because every request names its key, the keys can be spread over many machines by hashing them, and any client can compute where a key lives. Dynamo placed keys and machines on a ring — consistent hashing, invented at MIT in 1997 for web caches. Redis's own ways of splitting its keys come in lesson 19; the ring itself returns with Cassandra in lesson 22.
"A key-value store is a relational table with two columns, key and value." No: a table can be searched by its value column, indexed and joined. A key-value store has none of that; the only efficient question is the exact key. Redis adds operations on the value (next section), never a query over the values.
Redis: a dictionary served over the network
The section slide of p. 347 spells the name: REmote DIctionary Server. A dictionary — a hash map from keys to values — living in a server and answering over the network. Page 348, "What is REDIS ?", gives the definition:
Redis — "Redis is an advanced key-value store, where keys can contain data structures such as strings, hashes, lists, sets, and sorted sets. Supporting a set of atomic operations on these data types." The slide highlights the next sentence: "Redis is a different evolution path in the key-value databases where values are complex data types that are closely related to fundamental data structures and are exposed to the programmer as such, without additional abstraction layers."
Three ideas to keep apart. It is a key-value store: access by key, nothing else. The value under a key can be a data structure the server understands — a string, a hash, a list, a set, a sorted set. And the operations on those structures are atomic. The middle idea is what "advanced" means. To a plain key-value store a list is a string of bytes like any other; to Redis it is a list, so you send the operation instead of the value (Fig. 2).
Before: a plain key-value store
After: Redis
SET can fall between the two steps. Right: Redis knows the value is a list, "exposed to the programmer as such" (p. 348), so one atomic command appends on the server and returns the new length.The exercise session says the same in plain words: "The stored values can be simple types (e.g., numbers) or complex structures (e.g., lists)" (p. 1581). Values — keep that word in mind when you reread the first sentence of p. 348.
"In Redis a key can be a list or a hash." No: a key is always a string (binary-safe); the value stored under it is the string, hash, list, set or sorted set. The slide's "keys can contain data structures" is Redis's own old tagline and means that a key holds such a value, as the next sentence says: "values are complex data types" (so do the table of p. 354 and the session, p. 1581). Check it on a command: in HSET user:1 name John the key user:1 is a plain string, the hash with its field name is its value, and TYPE user:1 answers hash, the type of the value. If a true/false question quotes the slide's sentence, it is the slide's own definition: treat it as true, and in your own answers write "the value of a key can be".
The last line of p. 348: "Can be used as Database, a Caching layer or a Message broker", and each role has its reason in a box under it. A database, because "Redis can persist data to the disk": it can write snapshots and logs and reload them after a restart (lesson 19). A caching layer, because "Redis is fast": copies of data that is expensive to fetch or to compute are served from memory. A message broker, because "Redis is not only a key-value store": clients publish messages on channels that other clients subscribe to, or hand work through a list that a worker waits on.
Page 349, "What is not REDIS", draws the limits:
- "Redis is not a replacement for Relational Databases nor Document Stores."
- "It might be used complementary to a SQL relational store, and/or NoSQL document store."
- "Even when Redis offers configurable mechanisms for persistency, increased persistency will tend to increase latency and decrease throughput."
- "Best used for rapidly changing data with a foreseeable database size (should fit mostly in memory)."
Each limit follows from where the data lives. In memory, the dataset must fit in the RAM you can afford, so its size must be foreseeable. Persistence is a dial: the more often Redis writes to disk before it answers, the longer each write waits for the disk — the price you saw in the race. So the system of record stays elsewhere, and Redis holds what is small, hot and changing fast (Fig. 3).
The use cases of p. 350 are the roles at work; the table pairs each with what does the work in Redis. (If you ever serve a trained neural network in an application, the features it reads at prediction time live in the same kind of store: the feature-store lecture says they are "typically stored in low-latency databases like Redis", p. 735, lesson 29.)
| Use case (p. 350) | Role | What does the work |
|---|---|---|
| Caching; MVC Output Cache provider | caching layer | a value under a key, usually with a lifetime (lesson 19) |
| Counting things | database | a string holding an integer, increased on the server |
| Blocking queues | message broker | a list: push at one end, a pop that waits at the other |
| Pub/Sub (service bus); Backplane for SignalR; "Any real-time, cross-platform, cross-application communication" | message broker | channels: publishers send, every subscriber receives |
| ASP.NET Session State provider; Online user data (shopping cart, …) | database or cache | a hash per session, user or cart, often with a lifetime |
Page 351, "When to consider Redis", condenses all of this into four conditions — two reasons to choose Redis, then two limits it must respect:
- "Speed is critical" — the data is in memory and most commands take one step.
- "More than just key-value pairs" — you need the data structures and their atomic operations; for plain opaque values a simpler cache does the job (memcached, lesson 19).
- "Dataset can fit in memory" — the limit of p. 349.
- "Dataset is not critical" — you can afford to lose the latest changes if the server crashes, because making every write durable costs the speed you came for.
If you revise from the course notes: their p. 20 says that "being in-memory means that a single shutdown will cost you all your data". The slides say otherwise — "Redis can persist data to the disk" (p. 348). What a crash may cost is the most recent writes, depending on how persistence is set (lesson 19); that is the risk "Dataset is not critical" accepts.
Redis is a key-value store whose values are data structures the server understands: you send the operation, not the whole value.
One thread, one command at a time
Page 352, "Redis Architecture", is a list of facts. The plain ones first: Redis is "Written in ANSI C by Salvatore Sanfilippo (@antirez)", "Works in most POSIX systems like Linux, BSD and OS X", "Linux is the recommended", and there is "No official support for Windows" (the slide adds a Win-64 port maintained by Microsoft). Two more lines carry the exam.
Start from a case. Two nurses' tablets record a visit to the same ward at the same instant: both send INCR visits, and visits holds 10. Inside a Redis server there is no "same instant": the two commands wait in line and run one after the other, 10 → 11 → 12 (Fig. 4).
visits goes from 10 to 11 to 12, with no lock anywhere.The slide: "Redis is a single-threaded server, not designed to benefit from multiple CPU cores. Several Redis instances can be launched to scale out on several cores." And the consequence, one bullet later: "All operations are atomic (no two commands can run at the same time)."
Atomic command — a command that runs from start to end with no other command in between: no client can see it half done, and it happens entirely or not at all.
Single-threaded, so atomic, with no lock anywhere: a lock exists to keep two threads off the same data, and here there is only one thread. Two clients that send INCR at once always count twice; an LPUSH never meets a half-built list.
"All operations are atomic, so anything I send is safe." Each command is atomic. A GET followed by a SET is two commands, and another client's command can run between them — the lost update that the exercise session draws, and the reason INCR exists (lesson 18 replays it). Several commands become one atomic block only inside a transaction (MULTI … EXEC) or a Lua script: the advantages slide names "Atomic operations and Transactions" and "LUA scripting support" (p. 365) without teaching them — background beyond the exam's commands.
One thread sounds slow. It is fast for four reasons:
- The data is in memory: no disk sits on the path of a request, unless you make every write wait for one (the dial of p. 349) — the race of section 1.
- The steps are short: "It executes most commands in O(1) complexity and with minimal lines of code" (p. 352).
- Nothing waits for anything else: no locks to take, no switching between threads.
- One thread serves thousands of connections: it watches all of them at once and serves whichever has a command ready (an event loop; background).
Kleppmann adds a subtler reason in Designing Data-Intensive Applications (background): "the performance advantage of in-memory databases is not due to the fact that they don't need to read from disk … Rather, they can be faster because they can avoid the overheads of encoding in-memory data structures in a form that can be written to disk." A Redis list is a list in memory, not a page format to translate back and forth.
The design has a price. While one command runs, every other client waits, so a command over a huge value — all the members of a set with a million entries — holds up everybody; "most commands in O(1)" is what keeps the queue moving. And one thread uses one core: to use eight cores you run eight instances, each with part of the keys — the seed of partitioning (lesson 19).
Is Redis still single-threaded?
Mostly. Since Redis 6.0 (2020) reading and writing the network traffic can be spread over extra threads, and saving to disk runs in a separate child process. The commands themselves still execute one at a time on one thread, which is what the slide means, what makes them atomic, and what the exam expects you to say.
Page 353 draws the whole server on one slide, and it doubles as the map of this lesson and the next two (Fig. 5).
Read it as a table of contents. Left, the data structures: the next section, then the commands of lesson 18. Right, persistence: the "journal (text)" is the log of every write, the AOF, and the "snapshot (binary)" a picture of the whole dataset, the RDB file — the two mechanisms of p. 359. Below, the machinery for more than one server: replication keeps slaves as "exact copies of the master" (p. 359), Sentinel promotes a slave when the master dies, Cluster also spreads the keys over several masters (lesson 19).
One thread runs one command at a time: every command is atomic without a lock, and fast because each is a short step in memory.
Seven shapes for a value
Page 354, "Redis data types", lists what the value under a key can be: seven types, each with a picture, what it "Contains" and its "Read/write ability". Look at the pictures first (Fig. 6); the slide's text for each type is in the tabs below it.
Read the pictures in pairs. A list and a set both hold strings, but the list keeps the order of insertion and the repeats — C appears twice — while the set keeps neither: each string once, in no order. The exercise session gives the reason to pick a set: "SETS are useful as it is very quick to test the existence of a value, which is not as easy when it comes to lists" (p. 1600). A sorted set is a set whose members carry a number, the score, and stay in score order; A and C tie at 250 and are ordered by name (Redis breaks ties alphabetically; background). A hash is a small dictionary inside the value: its inner keys are called fields (HSET user:1 name John), so the Redis key names the object and the fields name its attributes.
The last two are built on the others. A geospatial index is "Sorted set implementation using geospatial information as the score": the position is packed into one number, so points near each other mostly get scores near each other and a radius search becomes a few ranges of scores (background) — TYPE on such a key answers zset. A HyperLogLog answers one question only, how many different items have been added, approximately and in at most 12 KB; it never gives an item back.
Contains: "Binary-safe strings (up to 512 MB), Integers or Floating point values, Bitmaps." Read/write ability: "Operate on the whole string, parts, increment/decrement the integers and floats, get/set bits by position."
Binary-safe means any bytes: a word, a JSON text, a whole JPEG. A string that holds a number can be increased on the server — the counter of "Counting things". In Python: str, bytes, or int when it holds a number. Use it for one value: a cached page, a counter, a flag.
# p. 355: bar held 223; returns (integer) 1223
INCRBY bar 1000
Contains: "Unordered hash table of keys to string values". Read/write ability: "Add, fetch, or remove individual items by key, fetch the whole hash."
The "keys" inside a hash are its fields. In Python: a dict of strings to strings. Use it for one object with named attributes — a user, a patient, a gas heater — read one field or all of them.
# p. 357: returns (integer) 1, the number of fields added to user:1
HSET user:1 name John
Contains: "Doubly linked list of strings". Read/write ability: "Push or pop items from both ends, trim based on offsets, read individual or multiple items, find or remove items by value."
Order of insertion, repeats allowed, cheap at both ends. In Python: a collections.deque. Use it for queues, stacks and "the latest N".
# p. 357: returns (integer) 1, the new length of the list jobs
RPUSH jobs "foo"
Contains: "Unordered collection of unique strings". Read/write ability: "Add, fetch, or remove individual items, check membership, intersect, union, difference, fetch random items."
No order, no repeats, a fast "is it in?". In Python: a set. Use it for tags, memberships and "what do these two have in common".
# p. 358: returns (integer) 2, the number of new members
SADD users "John" "Peter"
Contains: "Ordered mapping of string members to floating-point scores, ordered by score". Read/write ability: "Add, fetch, or remove individual items, fetch items based on score ranges or member value."
Unique members, each with a score, kept in score order. Python has no built-in twin: think of a dict from member to score that is always sorted by score. Use it for rankings, leaderboards and anything "sorted by year".
# p. 358: the score comes before the member; returns (integer) 3
ZADD scores 50 "Peter" 200 "Charles" 1000 "Mary"
Contains: "Sorted set implementation using geospatial information as the score". Read/write ability: "Add, fetch or remove individual items, search by coordinates and radius, calculate distance."
Use it for "what is near this point". The commands take the longitude first.
# the point of p. 354, longitude first; returns (integer) 1
GEOADD places -103.55328 20.63373 "Value"
Contains: "Probabilistic data structure to count unique things using 12Kb of memory". Read/write ability: "Add individual or multiple items, get the cardinality."
The cardinality is the number of different items. In Python terms: len(set(items)), approximately, without keeping the set. Use it for unique visitors or distinct searches when a small error is fine.
# returns (integer) 1: the structure changed
PFADD visitors "u17" "u03" "u17"
# returns (integer) 2: about two different visitors
PFCOUNT visitors
How can 12 KB count a billion different visitors?
Background, not on the slides: the idea behind HyperLogLog, with the two numbers the Redis documentation gives, 16,384 registers and 12 KB.
Hash every item. A good hash looks like a row of fair coin flips, and a returning visitor produces exactly the same row, so repeats change nothing.
Look at how each row starts. A run of \(k\) zeros at the front turns up about once in \(2^{k}\) different rows: if the longest run seen so far is 20, about a million different items have probably gone by. That is one small number, not the items.
One longest run is a noisy guess, so 14 bits of the hash send each item to one of \(2^{14} = 16\,384\) groups; each group keeps its own longest run in a register, and the registers are combined into one estimate.
A register stores only a run length, and 6 bits count up to 63, so the memory has a fixed ceiling whatever comes in:
\[ \begin{aligned} 16\,384 \times 6 &= 98\,304 \text{ bits} \\ &= 12\,288 \text{ bytes} \end{aligned} \]— the 12 KB of p. 354, the most it ever takes, for a thousand items or a billion.
The price is an error. With \(m = 16\,384\) registers the standard error is
\[ \frac{1.04}{\sqrt{m}} = \frac{1.04}{128} \approx 0.81\,\% \]— and, as with the standard error of a mean in statistics, it shrinks like one over the square root of what you average.
The slide's seven are the classic types. Newer versions add Streams (since Redis 5.0, 2018), a log of messages for queues, and modules such as JSON — background, not on the slides. Choosing a type is choosing which commands you get for free: ask what the question needs — order, uniqueness, a score, named fields, a position, a count of different things — and the type follows. Try it on eight cases.
In an exam exercise, write the type you chose and its reason in one line before the commands — "a hash: one key for the object, one field per attribute". The paper of 30 Jan 2026 asked for "a single key-value pair to store all the data of one Gas Heater" and named no type: there the choice is the point of the question (lesson 18 solves that paper; the exercise below trains the same choices on another paper's ER model).
Pick the type by the question you will ask: order and repeats, a list; uniqueness, a set; order by a number, a sorted set; named fields, a hash; one value or a counter, a string; a position, a geospatial index; how many different, a HyperLogLog.
The puzzle, answered
Back to the two choices of 2009 that sounded backwards. A database that answers only "what is under this key?" is the fix when a relational one is too slow, because that question costs one step in memory whatever the size of the data, with nothing to parse, plan or join — the flat line of the race. And Redis gives back much of what a plain key-value store loses: the value is a data structure, so a push, an increment or a membership test is still one command on one key.
One thread needs no lock because it cannot race with itself: commands run one after another, each atomic. It keeps up because every step is short and in memory, and when one core is not enough you start another instance. The price is printed on p. 349: the data must fit in memory, and the safer you make it on disk, the slower it gets.
The course introduction says that each category of systems "is covered along 5 dimensions": data model, "(declarative vs. imperative) query languages", data distribution, non-functional aspects and architectural solutions. A theory question on the features of Redis fits on that grid:
| Dimension | Redis |
|---|---|
| Data model | key → value: the key a string, the value one of seven data structures (pp. 348, 354) |
| Query language | nothing declarative: no SQL, no query over the values; imperative commands, each one operation on one key (lesson 18) |
| Data distribution | several instances "to scale out on several cores" (p. 352); replication, and partitioning that breaks up the data "across different hosts in a cluster" (p. 359, lesson 19) |
| Non-functional aspects | fast because in memory and most commands O(1); every command atomic; the dataset must fit in memory; more persistency, more latency and less throughput (pp. 349, 352) |
| Architecture | a single-threaded server in ANSI C; around the data structures, persistence, replication, networking, clients, Sentinel and Cluster (pp. 352–353) |
When the exam's one-point table asks which DB technology fits which entities (lesson 5), motivate a key-value row like this: data accessed only by its ID, read and written very often, small enough for memory and not critical — sessions, carts, counters, cached results, live rankings — in Redis.
Exam-style questions
Theory questions in the forms the theory part uses — short open answers, true/false and multiple choice, where a wrong tick may cost points — and one practical exercise in the style of the papers, on the ER model of a past paper. The Redis exercises of the past papers themselves are solved in lesson 18.
What is a key-value store? Explain why search by ID is usually built on top of a key-value store, and what a key-value store gives up compared with a relational database.
Show model answer
A key-value store is a dictionary: every value is stored under a unique key, typically a business key such as a tweet id, a flight number, an account number or an item number, and the only way to reach a value is through its key. The store does not interpret the value; its operations are put, get and delete by key. Search by ID is built on top of a key-value store because a lookup by key is the cheapest possible access: with a hash table in memory it takes constant time whatever the size of the data, and it needs no query parsing, planning or join. Compared with a relational database, which is queried using SQL and is key-based with foreign keys, indexes and joins, a key-value store keeps only the key: no queries on the content of the values, no foreign keys, no secondary indexes, no joins. Keys are used only to retrieve a value, not to search or to map tables to each other. In exchange the store is very fast and easy to split across machines by key.
Three things make the answer complete: the definition (one key, one opaque value, access only by key), the reason (constant-time lookup with no parsing, planning or joins) and the trade-off measured against the five items of p. 346. One example from p. 345 shows you know the slide.
What is Redis? Explain its definition, the three roles it can play, and what Redis is not.
Show model answer
Redis (REmote DIctionary Server) is an advanced key-value store in which the value stored under a key can be a data structure — a string, a hash, a list, a set or a sorted set — with a set of atomic operations on these data types. Unlike a plain key-value store, the values are complex data types close to the fundamental data structures and are exposed to the programmer as such, without additional abstraction layers, so the client sends an operation (append this element, add this member) and the server applies it. Redis can be used as a database, because it can persist data to disk; as a caching layer, because it is fast, the data being in memory; and as a message broker, because it is not only a key-value store (publish/subscribe, blocking queues). It is not a replacement for relational databases or document stores: it is used next to them. Increasing persistency increases latency and decreases throughput, and the dataset should fit in memory, so Redis is best used for rapidly changing data with a foreseeable size.
The three parts of p. 348, the three roles each with its reason, and the limits of p. 349. Prefer "the value of a key can be a list" to the slide's "keys can contain data structures" (the pitfall in section 2), but recognise the printed wording if a question quotes it.
True or false: since all operations in Redis are atomic, a client that reads a counter with GET and then writes the incremented value back with SET performs one indivisible operation.
Show model answer
False. Redis is single-threaded, so no two commands run at the same time and every single command is atomic. A GET followed by a SET is two commands: another client's command can be executed between them, so an update can be lost. A single INCR (or INCRBY) is atomic.
The trap is the word "all". Lesson 18 plays this race step by step. Wrong answers may carry a penalty (the rule is announced just before the exam): tick only what you can justify.
Redis is a single-threaded server. Explain why this makes every command atomic, why Redis is nevertheless fast, and how it can use more than one CPU core.
Show model answer
Redis executes commands on a single thread: the commands of all clients are queued and executed one at a time, each from start to end, so no two commands can run at the same time and no client can observe or interleave with a half-executed command. Every command is therefore atomic, and no locks are needed. Redis is nevertheless fast because the data is in memory, so no disk access is on the path of a request; because most commands run in O(1) and take very little time; because a single thread spends nothing on locks or on switching between threads; and because one event loop serves many connections. The cost is that a slow command, such as an O(N) operation on a large structure, delays every other client. Redis is not designed to benefit from multiple CPU cores: to use several cores, several Redis instances are launched, each holding part of the data.
Three questions, three answers; the chain single thread, then atomic, then no locks is the core of the answer. You may add as background that since Redis 6.0 network I/O can use helper threads, while commands still execute on one thread.
Which statements about the Redis data types are correct? Select all that apply.
Show model answer
Correct: the statements on the list, the sorted set, the geospatial index and the string. A set is unordered; a HyperLogLog only estimates the number of distinct items and cannot return them.
A select-all question where wrong ticks may cost points: the two false statements are the classic confusions, list against set and counting against storing.
Exam-style exercise, written for this notebook on the ER model of the exam of 30 May 2025 (its header prints June 30, 2025), tracking puzzles' production and sales; that paper has no Redis exercise. The part used: Puzzle (Puzzle ID, Name, Collection Name (e.g., Museum Collection), Number of Pieces, Width, Height, Description), produced by one Company (Produce, with Production Date: Company (1, N) – Puzzle (1, 1)); User (Personal ID, Name, Surname, Age, Birth Date, City, Country), who buys puzzles (Buy, with Buy Date: Puzzle (0, N) – User (0, N)). N.B. All sizes are in cm.
Exercise – Redis. For each request, state the Redis data type you use and why, in one line, then write the commands.
(1) Create a single key-value pair to store all the data of one Puzzle, with all the attributes describing the object.
(2) Store the puzzles of the "Museum Collection" sorted by their number of pieces. Then, query them to get the puzzle with the most pieces.
(3) Store the countries of the users who bought the puzzle "P1", each country only once. Then, check whether "Italy" is one of them.
Show model answer
(1) A hash: one key for the puzzle and one field for each of its attributes, so a single attribute can be read or changed on its own. The values are examples, and the attribute names are written with underscores (a field name with spaces would need double quotes).
HSET puzzle:P1 Puzzle_ID "P1" Name "Starry Night" Collection_Name "Museum Collection" Number_of_Pieces 1000 Width 70 Height 50 Description "Van Gogh, 1889"
The reply is (integer) 7, the number of fields created. One string holding the whole puzzle as JSON would also be a single key-value pair, but reading one attribute would then mean reading the whole text.
(2) A sorted set: the number of pieces is the score, so Redis keeps the puzzles in that order whatever the order of insertion. The highest score is the last element, at index -1, so the second command returns "P3".
ZADD museum:by_pieces 1000 "P1" 500 "P2" 2000 "P3"
ZRANGE museum:by_pieces -1 -1
(3) A set: each country is kept once, however many users from it bought the puzzle, and the membership test is one command. SADD replies (integer) 3, because the second "Italy" is ignored; SISMEMBER replies (integer) 1.
SADD puzzle:P1:countries "Italy" "France" "Italy" "Spain"
SISMEMBER puzzle:P1:countries "Italy"
Written for this notebook in the wording of the papers; no official solution exists for it, nor for any past paper. It trains the choice that the exam of 30 Jan 2026, exercise 5, asks on its hospital ER model (solved in lesson 18). What makes each answer complete: (1) every attribute of Puzzle under one key — a hash, or JSON in a string; (2) a structure that keeps the order by itself, the score written before the member, and the right end read: index 0 is the lowest score, -1 the highest — a list would need the puzzles pushed already in order; (3) uniqueness and membership, the two things a set gives for free and a list does not ("very quick to test the existence of a value", p. 1600).
Check yourself
A key-value store keeps every blog post under keys like post:101, with the whole page as the value. Which request can it not answer by itself?
In the lookup race, choose "RAM, everything cached" and grow N from a million to a billion. What happens?
Why does RPUSH jobs "baz" on Redis beat GET, append and SET on a plain key-value store (Fig. 2)?
Which of these follow from Redis executing commands on a single thread? Select all that apply.
Atomic per command, not per conversation: that line separates this lesson's theory from the INCR of lesson 18.
In HSET user:1 name John, which part is the data structure that p. 348 means by "keys can contain data structures"?
A screen lists a hospital's buildings from the newest to the oldest by year of construction, and new records are added over time in any order. Which type keeps them in that order without your code sorting them?
A hospital plans to keep all its patients' medical records — 60 TB, growing every year, and by law never to be lost — only in Redis. Which conditions of p. 351 does the plan clearly violate? Select all that apply.
Redis belongs next to the system of record (Fig. 3), not in its place.
Key take-aways
- A key-value store maps a business key to a value and answers only "what is under this key?" with put, get and delete; search by ID is usually built on one, because a lookup by key in memory takes one step whatever the size of the data.
- A relational database is queried using SQL and is key-based with foreign keys, indexes and joins; a key-value store keeps only the key, gives up queries on values, joins and secondary indexes, and gains speed and an easy split of the keys across machines.
- Redis, the REmote DIctionary Server, is an advanced key-value store whose values are data structures exposed as such, with atomic operations on them; it serves as a database, a caching layer or a message broker, next to a relational or document store and never instead of it.
- Consider Redis when speed is critical, you need more than key-value pairs, the dataset fits in memory and the data is not critical; more persistency means more latency and less throughput.
- Redis, written in ANSI C, executes commands on one thread: no two commands run at the same time, so each is atomic with no locks, and it stays fast because each step is short and in memory; more cores mean more instances.
- The seven types: string (bytes, numbers, bitmaps), hash (fields to values), list (ordered, repeats, both ends), set (unique, unordered, membership and set algebra), sorted set (members ordered by score), geospatial index (a sorted set scored by position) and HyperLogLog (an approximate count of distinct items in 12 KB) — choose by the question you will ask.
What to watch and read
-
Redis in 100 Seconds
Fireship
A very short tour of an in-memory key-value store whose values have types — the hook of this lesson in motion.
-
Redis data types
Redis documentation
One page per type with its commands and their complexity; open it next to the tabs of section 4, and read the sorted-set page in full.
-
Redis Sandbox
Redis
A Redis console in the browser, no install: type the commands of the tabs and of the widget and compare the replies. Writes go to a temporary session whose keys must start with
pg:, so typeHSET pg:user:1 name John. The slide's "Online Demo: http://try.redis.io" no longer resolves; this is its official replacement. -
A Decade of Dynamo
Werner Vogels, 2017
The story behind the 70 per cent of section 1: why Amazon built a key-value store instead of tuning its relational database, and what came of it.
-
REmote DIctionary Server
Chris Keith and James Tavares, Brown CS227, 2011
The deck p. 354 cites for "Redis data types internals": how each type is built inside (a skip list for sorted sets), with Redis's early history.