Redis Lists (Part 1)

A list is an ordered, repeatable sequence of strings. This lesson covers basic list operations.

What is a List?

A list is similar to:

Redis list features:

mylist
├─ "element1"
├─ "element2"
├─ "element3"
└─ "element4"
💡 Internal implementation: Redis lists use quicklist, a combination of doubly-linked list and ziplist that balances memory and performance.

LPUSH and RPUSH: Insert Elements

LPUSH: Insert from the Left (Head)

REDIS
# Insert a single element from the left
LPUSH mylist "world"
(integer) 1  # Returns list length

# Insert multiple elements from the left
LPUSH mylist "hello"
(integer) 2

# View the list
LRANGE mylist 0 -1
1) "hello"
2) "world"
⚠️ Note: When inserting multiple elements with LPUSH, they are inserted left-to-right in parameter order. LPUSH mylist a b c results in [c, b, a, ...].

RPUSH: Insert from the Right (Tail)

REDIS
# Insert from the right
RPUSH mylist "Redis"
(integer) 3

RPUSH mylist "Tutorial"
(integer) 4

# View the list
LRANGE mylist 0 -1
1) "hello"
2) "world"
3) "Redis"
4) "Tutorial"

LPUSHX and RPUSHX: Insert Only if List Exists

REDIS
# Insert fails when list does not exist
LPUSHX notexist "value"
(integer) 0

# Insert succeeds when list exists
LPUSHX mylist "first"
(integer) 5

RPUSHX mylist "last"
(integer) 6

LPOP and RPOP: Pop Elements

LPOP: Pop from the Left (Head)

REDIS
# View current list
LRANGE mylist 0 -1
1) "first"
2) "hello"
3) "world"
4) "Redis"
5) "Tutorial"
6) "last"

# Pop from the left
LPOP mylist
"first"

# Pop multiple elements (Redis 6.2+)
LPOP mylist 2
1) "hello"
2) "world"

RPOP: Pop from the Right (Tail)

REDIS
# Pop from the right
RPOP mylist
"last"

# Pop multiple elements (Redis 6.2+)
RPOP mylist 2
1) "Tutorial"
2) "Redis"

When List is Empty

REDIS
LPOP emptylist
(nil)  # Returns nil for empty list

LLEN: Get List Length

REDIS
LPUSH mylist "a" "b" "c"
LLEN mylist
(integer) 3

# List does not exist
LLEN notexist
(integer) 0

LRANGE: Get Elements Within a Range

LRANGE is the most common list query command.

Basic Usage

REDIS
LPUSH mylist "one" "two" "three" "four" "five"

# Get all elements
LRANGE mylist 0 -1
1) "five"
2) "four"
3) "three"
4) "two"
5) "one"

# Get first 3 elements
LRANGE mylist 0 2
1) "five"
2) "four"
3) "three"

# Get last 2 elements
LRANGE mylist -2 -1
1) "two"
2) "one"

# Get elements at index 1 through 3
LRANGE mylist 1 3
1) "four"
2) "three"
3) "two"

Index Rules

Index Description
0 First element
1 Second element
-1 Last element
-2 Second to last element
0 -1 All elements
⚠️ Note: The end index in LRANGE is inclusive. LRANGE 0 2 returns elements at indexes 0, 1, 2 (3 elements total).

Implementing Queues and Stacks with Lists

Queue (FIFO: First In, First Out)

Using RPUSH + LPOP:

REDIS
# Producer: enqueue from the right
RPUSH queue:task "task1"
RPUSH queue:task "task2"
RPUSH queue:task "task3"

# Consumer: dequeue from the left
LPOP queue:task
"task1"

LPOP queue:task
"task2"
Enqueue → [task1, task2, task3] → Dequeue
          RPUSH               LPOP

Stack (LIFO: Last In, First Out)

Using LPUSH + LPOP:

REDIS
# Push
LPUSH stack:data "item1"
LPUSH stack:data "item2"
LPUSH stack:data "item3"

# Pop
LPOP stack:data
"item3"

LPOP stack:data
"item2"
Push → [item3, item2, item1] → Pop
       LPUSH                LPOP
💡 Memory aid:

  • Queue: RPUSH + LPOP (right in, left out)
  • Stack: LPUSH + LPOP (left in, left out)

Blocking Pop: BLPOP and BRPOP

When the list is empty, BLPOP and BRPOP block until an element is available or a timeout occurs.

BLPOP: Blocking Left Pop

REDIS
# Client 1: wait for a task in the queue (max 10 seconds)
BLPOP queue:task 10

# Client 2: add a task
RPUSH queue:task "new_task"

# Client 1 receives:
1) "queue:task"  # List name
2) "new_task"    # Popped element

BRPOP: Blocking Right Pop

REDIS
BRPOP queue:task 10

Blocking on Multiple Lists

REDIS
# Wait on multiple lists, return whichever has data first
BLPOP queue:high queue:low 10
💡 Use case: BLPOP/BRPOP are commonly used for implementing task queues and message queues, where consumers block waiting for new tasks.

List Use Cases

Use Case 1: Message Queue

REDIS
# Producer: send a message
RPUSH queue:email '{"to":"user@example.com","subject":"Hello"}'

# Consumer: receive a message (blocking wait)
BLPOP queue:email 0

Use Case 2: Recent List

REDIS
# Add latest articles
LPUSH articles:latest "article:123"
LPUSH articles:latest "article:124"
LPUSH articles:latest "article:125"

# Get latest 10 articles
LRANGE articles:latest 0 9

# Keep the list at most 100 articles
LTRIM articles:latest 0 99

Use Case 3: Timeline

REDIS
# Publish a post (add to user timeline)
LPUSH timeline:user:1 "post:1001"
LPUSH timeline:user:1 "post:1002"

# View timeline (latest 20 posts)
LRANGE timeline:user:1 0 19

Use Case 4: Operation Log

REDIS
# Record user actions
RPUSH log:user:1 "login at 2026-06-23 10:00:00"
RPUSH log:user:1 "view article:123"
RPUSH log:user:1 "like article:123"

# View recent actions
LRANGE log:user:1 -10 -1

LTRIM: Trim the List

LTRIM retains elements within a specified range and deletes everything else.

REDIS
LPUSH mylist "one" "two" "three" "four" "five"

# Keep only the first 3 elements
LTRIM mylist 0 2
OK

LRANGE mylist 0 -1
1) "five"
2) "four"
3) "three"

Use Case: Maintain a Fixed-Size List

REDIS
# Add a new article and keep at most 100
LPUSH articles:latest "article:new"
LTRIM articles:latest 0 99
💡 Tip: LPUSH + LTRIM together maintain a capped list of the latest items.

❓ FAQ

Q What is the maximum number of elements in a list?
A Up to 2^32 - 1 (about 4.2 billion), but practically limited by memory.
Q How fast are LPUSH and RPOP?
A O(1) time complexity — very fast. Head and tail operations are constant time.
Q How fast is LRANGE?
A O(N), where N is the number of returned elements. Getting a large range is slower.
Q Does BLPOP block indefinitely?
A No. Set a timeout; after the timeout, it returns nil. A timeout of 0 means wait forever.
Q What about inserting in the middle of a list?
A Use LINSERT, but it has O(N) performance. It's recommended to only operate at the head and tail.

📖 Summary

📝 Exercises

  1. Queue implementation: Use RPUSH and LPOP to implement a task queue, simulating a producer and consumer
  2. Stack implementation: Use LPUSH and LPOP to implement a stack, simulating push and pop
  3. Recent list: Implement a recent articles list, adding articles and keeping at most 10
  4. Blocking wait: Use BLPOP to implement a blocking task queue (needs two terminals)

Next Lesson

In the next lesson, we will learn Redis Lists (Part 2), covering query, modification, and advanced list operations.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏