Lists and simple queues

Redis · Essentials · 9 min

Lists power job queues, recent-activity feeds and capped logs with O(1) pushes and pops at both ends.

A list is an ordered sequence of strings, fast to change at both ends. LPUSH/RPUSH add to the left/right, LPOP/RPOP remove (optionally several with a count), LLEN gives the length and LRANGE key 0 -1 reads a range by index (negative indexes count from the end).

Pick the ends to get the behaviour you want:

  • queue (FIFO): LPUSH to add, RPOP to take,
  • stack (LIFO): LPUSH and LPOP,
  • capped list: LPUSH then LTRIM key 0 99 keeps the newest 100 items, perfect for "recent activity".

Workers shouldn't poll in a loop. BRPOP queue 5 blocks until an item arrives or 5 seconds pass (0 = wait forever) and can watch several lists at once, giving priority by order.

Popping removes the item, so a worker that crashes after BRPOP loses the job. LMOVE source processing RIGHT LEFT (and its blocking form BLMOVE) atomically moves the item to a processing list, so you can remove it after success and requeue stragglers. For real at-least-once delivery with acknowledgements and consumer groups, Redis streams are the better tool.

Access by index (LINDEX, LSET) and LREM are O(N), so lists are for ends and ranges near the ends, not random access.

Example

redis-cli RPUSH jobs email:1 email:2 email:3    # (integer) 3
redis-cli LPOP jobs                             # "email:1"  (FIFO with RPUSH + LPOP)
redis-cli LMOVE jobs jobs:processing LEFT RIGHT # "email:2"  safe hand-off
redis-cli LRANGE jobs:processing 0 -1           # 1) "email:2"
redis-cli LREM jobs:processing 1 email:2        # (integer) 1  done, remove it

# capped feed of the 3 newest events
for e in a b c d e; do redis-cli LPUSH feed:42 "$e" > /dev/null; done
redis-cli LTRIM feed:42 0 2                     # OK
redis-cli LRANGE feed:42 0 -1                   # 1) "e"  2) "d"  3) "c"

redis-cli BRPOP empty-queue 1                   # (nil) after waiting 1 second

Remember

  • LPUSH/RPUSH and LPOP/RPOP are O(1) at either end
  • LPUSH + LTRIM keeps a capped list of the newest items
  • BRPOP/BLMOVE let workers block instead of polling
  • LMOVE to a processing list avoids losing jobs on crashes

Watch out for

  • Using LINDEX or LREM on long lists in hot paths: they are O(N).

Check yourself

  1. You LPUSH events and want only the newest 50. Which command keeps them?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: redis.io/docs/latest/develop/data-types/lists/