Foundations 5 of 5 · Visual guide

Lists and sets in depth

A list remembers order and allows duplicates. A set forgets order and refuses duplicates. Pick by the question you will ask.

Anatomy of a list

A Redis list Five items in a row. Index 0 is the head on the left, minus 1 is the tail on the right. LPUSH and LPOP work on the left, RPUSH and RPOP on the right, both in constant time. Reaching the middle walks the list. LPUSH → ← RPUSH e d c b a 01234 -5-4-3-2-1 head tail LINDEX 2 walks from an end · O(n) both ends · O(1), any length LRANGE list 0 -1 → e d c b a
  1. LPUSH adds at the left, the head. The newest item is always index 0.
  2. RPUSH adds at the right, the tail.
  3. Indexes count from the head (0, 1, 2…) or from the tail (-1, -2…). LRANGE list 0 -1 reads everything.
  4. LPOP and RPOP remove from either end in constant time, even for a list of millions.
  5. Reaching into the middle (LINDEX 2, LINSERT, LSET) walks the list. Fine for short lists, slow for huge ones.
A list is a double-ended queue. The ends are cheap; the middle is not.

Stack, queue, capped feed

Three list patterns Stack: push and pop on the same side, last in first out. Queue: push left, pop right, first in first out. Capped feed: push left then LTRIM 0 4, so only the five newest stay. Stack · LIFO 3 2 1 LPUSH + LPOP undo history Queue · FIFO 3 2 1 LPUSH + BRPOP job queue Capped feed 6 5 4 3 2 1 trimmed LPUSH + LTRIM 0 4 “last 5 notifications”
Same structure, three behaviors, decided only by which ends you push and pop.

List lab

Commands
LPUSH / RPUSH key v [v …]
LPOP / RPOP key
LRANGE key 0 -1    LLEN key
LINDEX key -1      LTRIM key 0 99
BLPOP / BRPOP key 5    # wait up to 5 s
LMOVE src dst LEFT RIGHT
In real life

Activity feeds and “recently viewed” (LPUSH + LTRIM), simple job queues (LPUSH + BRPOP), chat history for one room.

Watch out

LRANGE key 0 -1 on a list of a million items blocks Redis. Page it: LRANGE key 0 49. An empty list is deleted automatically.

Sets and set algebra

Intersection, union, difference Three pairs of overlapping circles. SINTER shades only the overlap. SUNION shades both circles. SDIFF shades the left circle minus the overlap. SINTER a b in both · mutual friends SUNION a b in either · merged audience SDIFF a b in a, not b · not yet seen SADD a x → 1 · SADD a x → 0 (already there)
  1. SINTER: members in both sets. “People who follow Ana and Ben.”
  2. SUNION: members in either set, each once. “Everyone tagged redis or cache.”
  3. SDIFF: members of the first set not in the others. “Posts this user has not seen yet.”
  4. And the rule underneath it all: a member is stored once. SADD returns 0 for a duplicate, which makes sets perfect for “have I processed this id?”.
All three run inside Redis. Use the …STORE variants (SINTERSTORE dest a b) to save the result as a new set.

Set lab

Commands
SADD / SREM key m [m …]
SISMEMBER key m    SCARD key
SMEMBERS key       SSCAN key 0
SINTER / SUNION / SDIFF a b
SRANDMEMBER key    SPOP key
In real life

Tags, “who is online” (SADD online u42), idempotency (“already sent this webhook?”), random winner picks with SPOP.

Watch out

No order. Need “newest first” or a score? Use a sorted set. SMEMBERS on a huge set blocks — iterate with SSCAN.

List, set, sorted set, or hash?

Pick by the question you ask
“What came first / last?”List — order of arrival, duplicates allowed.
“Is x in there?”Set — unique members, O(1) membership, set algebra.
“Who ranks highest?”Sorted set — unique members ordered by a score. Leaderboard.
“What is field f of object o?”Hash — fields of one object. Cart.

Quick check

You LPUSH every page a user visits. How do you keep only the last 20?
Show answer

LPUSH recent:u42 /page then LTRIM recent:u42 0 19, ideally in one MULTI or pipeline.

A webhook can arrive twice. How do you process each event id once?
Show answer

SADD seen:webhooks evt_91. If it returns 1, process; if 0, skip. Add a TTL or a daily key so the set does not grow forever.