Redis · lesson 3 of 14
Beginner
4Intermediate
7- 5 MULTI/EXEC Transactions and the WATCH-Based Optimistic Lock
- 6 Pub/Sub: Channels, Patterns, and the Message That Never Arrives
- 7 RDB vs AOF: What Survives a Hard Kill and What Doesn't
- 8 Replication: A Read-Only Replica, and What WAIT Actually Guarantees
- 9 ACL: a User Restricted to One Key Pattern and One Command
- 12 maxmemory and Eviction: What Redis Throws Away When It's Full
- 13 Cache-Aside with Redis: Stale Reads, Races and Stampedes
Advanced
3Also part of Redis
3Hashes, Lists, and Sets: Structures That Deduplicate and Enforce Order For You
SADD silently drops duplicates and returns how many were actually new, RPUSH+LPOP gives you a FIFO queue for free, and HINCRBY enforces numeric fields the same way INCR does for strings.
By SkillByExample · Published
Three data types, three ways Redis does bookkeeping a plain string key can’t: grouped fields, guaranteed order, and automatic deduplication.
Hashes: a record in one key
docker exec redis-lesson redis-cli HSET book:1 title "Dune" author "Herbert" year 1965
docker exec redis-lesson redis-cli HGETALL book:1
3
title
Dune
author
Herbert
year
1965
HSET returns 3 — the number of new fields set, not a success flag. HGETALL returns a
flat field-value-field-value sequence; most client libraries turn this into a dict or map
automatically, but redis-cli shows the raw shape.
docker exec redis-lesson redis-cli HGET book:1 title
docker exec redis-lesson redis-cli HINCRBY book:1 year 1
Dune
1966
HGET reads a single field. HINCRBY does the same atomic increment as INCR, scoped to one
field of a hash — useful for a per-record counter (view count, stock level) that lives
alongside other fields instead of needing its own top-level key.
The bug: incrementing a non-numeric field
docker exec redis-lesson redis-cli HINCRBY book:1 title 1
ERR hash value is not an integer
Same enforcement as INCR on a string, scoped to a single field — title holds "Dune",
which isn’t numeric, so HINCRBY refuses rather than guessing.
Sets: unique, unordered, and self-deduplicating
docker exec redis-lesson redis-cli SADD tags:1 scifi classic scifi
docker exec redis-lesson redis-cli SMEMBERS tags:1
docker exec redis-lesson redis-cli SCARD tags:1
2
scifi
classic
2
SADD was given scifi twice in the same call and reports 2 — only two distinct values
went in. SCARD (set cardinality) confirms 2 members, not 3.
docker exec redis-lesson redis-cli SADD tags:1 scifi
0
Adding scifi again, in a separate call, returns 0 — nothing changed, because it was
already there. This makes SADD’s return value a free “was this actually new” check, without
a separate SISMEMBER call first.
Set algebra: intersect, union, diff
docker exec redis-lesson redis-cli SADD tags:2 scifi series
docker exec redis-lesson redis-cli SINTER tags:1 tags:2
docker exec redis-lesson redis-cli SUNION tags:1 tags:2
docker exec redis-lesson redis-cli SDIFF tags:1 tags:2
2
scifi
series
classic
scifi
classic
Three different books tagged this way, and finding “tags common to both” (SINTER), “every
tag across both” (SUNION), or “tags only the first book has” (SDIFF) is one command each —
no client-side set logic needed.
Lists as a FIFO queue
docker exec redis-lesson redis-cli RPUSH queue:jobs job1 job2 job3
docker exec redis-lesson redis-cli LPOP queue:jobs
docker exec redis-lesson redis-cli LLEN queue:jobs
3
job1
2
RPUSH adds to the tail; LPOP removes from the head. Push at one end, pop from the other,
and the first value in is the first one out — a real FIFO queue built from one data type, no
separate queue construct needed.
The bug that isn’t one: popping more than exists
docker exec redis-lesson redis-cli LPOP queue:jobs 5
job2
job3
Only 2 elements were left; asking for 5 didn’t error — LPOP with a count just returns
whatever is actually there, up to that count. Code expecting exactly 5 elements back needs to
check the length of the result, not assume the request was fully satisfied.
Practice
1. Check set membership directly instead of fetching the whole set.
docker exec redis-lesson redis-cli SISMEMBER tags:1 scifi
docker exec redis-lesson redis-cli SISMEMBER tags:1 horror
1
0
SISMEMBER answers “is this one value in the set” in O(1), without transferring the whole
set the way SMEMBERS plus a client-side check would.
2. Delete one field from a hash without touching the rest of the record.
docker exec redis-lesson redis-cli HDEL book:1 author
docker exec redis-lesson redis-cli HGETALL book:1
1
title
Dune
year
1966
HDEL removes just the named field or fields — author is gone, title and year are
untouched. 1 is the count of fields actually deleted.
3. Push onto both ends of the same list and observe the resulting order.
docker exec redis-lesson redis-cli DEL mixed
docker exec redis-lesson redis-cli RPUSH mixed b c
docker exec redis-lesson redis-cli LPUSH mixed a
docker exec redis-lesson redis-cli LRANGE mixed 0 -1
0
2
3
a
b
c
RPUSH b c builds [b, c], returning length 2; LPUSH a inserts at the head, returning the
new length 3 — both push commands return the list’s length after the push, not the number of
elements added. The final [a, b, c] shows a list can be built from both ends, which is
exactly how it supports both a stack (one end only) and a queue (opposite ends) depending on
which commands a program uses.
Next: sorted sets — ordering by score, and building a leaderboard.