Core Data Structures I: Strings, Lists, Hashes
๐งฑ Core Data Structures I: Strings, Lists, Hashes
SET/GET only scratched Redis's simplest data type. Redis is really a data structure store โ strings, lists, hashes, and (Chapter 4) sets and sorted sets โ each suited to a different shape of data, all sitting behind the same simple command style.
Strings: More Than Just SET/GET
A Redis string holds a single value โ but beyond plain SET/GET, Redis provides INCR/DECR for atomic increments: safe to call from many concurrent clients at once with no race condition, since the increment happens as one indivisible server-side operation.
Two concurrent requests both calling INCR at the exact same instant will still produce two distinct, correct results (e.g. 1 and 2, never both landing on 1) โ a guarantee that would need explicit locking to replicate safely in most other systems.
Lists: Ordered Collections
A Redis list is an ordered sequence of values โ LPUSH inserts at the head (left/beginning), RPUSH inserts at the tail (right/end), and LRANGE reads a range of elements.
LRANGE key 0 -1 is the standard idiom for "give me the whole list" โ 0 is the first element, -1 refers to the last element regardless of the list's length.
Hashes: Field-Value Pairs Within One Key
A Redis hash groups multiple field-value pairs under a single key โ the natural fit for something object-like, such as a user profile, without needing a separate top-level key per field.
Multiple String Keys vs. One Hash
Multiple Strings
One Hash
The hash consolidates related fields under one key โ reading, updating, or deleting "this user's data" is one key to manage, not an ever-growing set of loosely related string keys sharing a naming convention.
| Command | Structure | Purpose |
|---|---|---|
SET / GET | String | Store/retrieve a single value |
INCR / DECR | String | Atomic increment/decrement of a numeric value |
LPUSH / RPUSH | List | Insert at the head / tail of an ordered list |
LRANGE | List | Read a range of elements (0 -1 = whole list) |
HSET / HGET | Hash | Set/get one field within a hash |
HGETALL | Hash | Read every field-value pair in a hash |
Use a String When
The value is a single, simple piece of data โ a counter, a flag, a cached blob of text or serialized JSON.
Use a List When
Order matters and you're modeling a sequence โ a recent-activity feed, a simple queue (Chapter 7 goes deeper on this).
Use a Hash When
You're modeling one object with multiple named fields โ a user profile, a product record โ grouped under a single key.
Coming Up: Sets & Sorted Sets
Chapter 4 covers unique unordered collections and score-ordered collections โ leaderboards, tag systems, and more.
๐ป Coding Challenges
Challenge 1: Build a View Counter
Write the redis-cli commands to initialize a view counter for a page called page:about at 0, then increment it three times, showing the value after each increment.
Goal: Practice using INCR for a realistic atomic-counter scenario.
Challenge 2: Predict List Order
Starting from an empty list queue:tasks, predict the final order of elements after running: RPUSH queue:tasks "A", RPUSH queue:tasks "B", LPUSH queue:tasks "C". Show the LRANGE command that would confirm your answer.
Goal: Practice reasoning about how LPUSH and RPUSH insert relative to each other, not just in isolation.
Challenge 3: Model a Product as a Hash
Write the HSET command to store a product with key product:200 having fields name ("Wireless Mouse"), price ("24.99"), and category ("electronics"), then the command to read all of it back.
Goal: Practice choosing a hash over separate string keys for a naturally object-shaped record.
RPUSH appends to the end, in the order called โ repeated RPUSH calls preserve the order they were issued in. LPUSH, by contrast, inserts at the head each time โ so repeated LPUSH calls actually end up in reverse order relative to the sequence they were called in, since each new element pushes the previous head further right. Mixing LPUSH and RPUSH on the same list without tracking this carefully is a common source of "why is my list in the wrong order" bugs โ always be deliberate about which end a given piece of code pushes to, and check with LRANGE rather than assuming.
๐ฏ What's Next
The next chapter covers Sets & Sorted Sets โ SADD/SINTER for unique unordered collections, and ZADD/ZRANGE for score-ordered collections, including the leaderboard and sliding-window-counter patterns.