Redis Lists (Part 2)
This lesson covers advanced list operations including querying, modifying, and inserting elements.
LINDEX: Get Element by Index
LINDEX retrieves an element by its index without removing it.
Basic Usage
LPUSH mylist "one" "two" "three" "four" "five"
# Get the first element (index 0)
LINDEX mylist 0
"five"
# Get the second element
LINDEX mylist 1
"four"
# Get the last element
LINDEX mylist -1
"one"
# Get the second to last element
LINDEX mylist -2
"two"
Index Out of Range
# Returns nil when index is out of range
LINDEX mylist 10
(nil)
LINDEX mylist -10
(nil)
LSET: Set Element by Index
LSET modifies the element at a specified index.
Basic Usage
LRANGE mylist 0 -1
1) "five"
2) "four"
3) "three"
4) "two"
5) "one"
# Modify the first element
LSET mylist 0 "FIRST"
OK
# Modify the last element
LSET mylist -1 "LAST"
OK
LRANGE mylist 0 -1
1) "FIRST"
2) "four"
3) "three"
4) "two"
5) "LAST"
Index Out of Range
LSET mylist 10 "value"
(error) ERR index out of range
LINSERT: Insert Before or After a Pivot
LINSERT inserts a new element before or after a specified pivot element.
LINSERT BEFORE: Insert Before
LRANGE mylist 0 -1
1) "FIRST"
2) "four"
3) "three"
4) "two"
5) "LAST"
# Insert "BEFORE_THREE" before "three"
LINSERT mylist BEFORE "three" "BEFORE_THREE"
(integer) 6 # Returns list length
LRANGE mylist 0 -1
1) "FIRST"
2) "four"
3) "BEFORE_THREE"
4) "three"
5) "two"
6) "LAST"
LINSERT AFTER: Insert After
# Insert "AFTER_THREE" after "three"
LINSERT mylist AFTER "three" "AFTER_THREE"
(integer) 7
LRANGE mylist 0 -1
1) "FIRST"
2) "four"
3) "BEFORE_THREE"
4) "three"
5) "AFTER_THREE"
6) "two"
7) "LAST"
Pivot Not Found
# Specified pivot element does not exist
LINSERT mylist BEFORE "notexist" "value"
(integer) -1 # Returns -1 when pivot not found
LREM: Remove Elements by Value
LREM removes elements from the list that match a specified value.
Basic Usage
LPUSH mylist "a" "b" "a" "c" "a" "d"
LRANGE mylist 0 -1
1) "d"
2) "a"
3) "c"
4) "a"
5) "b"
6) "a"
# Remove 2 occurrences of "a" from the head
LREM mylist 2 "a"
(integer) 2 # Deleted 2
LRANGE mylist 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
Parameter Reference
| Parameter | Description |
|---|---|
| count > 0 | Remove count occurrences from the head |
| count < 0 | Remove abs(count) occurrences from the tail |
| count = 0 | Remove all matching elements |
Remove from Tail
LPUSH mylist "a" "b" "a" "c" "a"
# Remove 1 occurrence of "a" from the tail
LREM mylist -1 "a"
(integer) 1
Remove All Matching Elements
LPUSH mylist "a" "b" "a" "c" "a"
# Remove all "a"
LREM mylist 0 "a"
(integer) 3
LRANGE mylist 0 -1
1) "c"
2) "b"
RPOPLPUSH: Move Elements
RPOPLPUSH pops the tail element from one list and pushes it to the head of another list.
Basic Usage
# Source list
LPUSH source "one" "two" "three"
# Destination list
LPUSH destination "a" "b"
# Move tail of source to head of destination
RPOPLPUSH source destination
"one" # Returns the moved element
LRANGE source 0 -1
1) "three"
2) "two"
LRANGE destination 0 -1
1) "one"
2) "a"
3) "b"
Use Case: Circular Queue
# Move a task from tail back to head for round-robin processing
RPOPLPUSH queue:task queue:task
Use Case: Backup Queue
# Move task to backup queue while processing
RPOPLPUSH queue:task queue:backup
# If processing fails, the task can be recovered from the backup queue
BRPOPLPUSH: Blocking Move
BRPOPLPUSH is the blocking version of RPOPLPUSH.
# If source list is empty, block wait for up to 10 seconds
BRPOPLPUSH source destination 10
LMOVE: Move Elements (Redis 6.2+)
LMOVE is a generalized version of RPOPLPUSH that lets you specify both the source and destination positions.
# Pop from the right of source, push to the left of destination
LMOVE source destination RIGHT LEFT
# Pop from the left of source, push to the right of destination
LMOVE source destination LEFT RIGHT
Advanced List Applications
Use Case 1: Pagination
# Article list
LPUSH articles "article:1" "article:2" ... "article:100"
# Page 1 (10 items per page)
LRANGE articles 0 9
# Page 2
LRANGE articles 10 19
# Page 3
LRANGE articles 20 29
Use Case 2: Recent Contacts
# Add a contact to the recent list
LPUSH contacts:user:1 "user:2"
# If already exists, remove first then add (move to front)
LREM contacts:user:1 0 "user:2"
LPUSH contacts:user:1 "user:2"
# Get recent 10 contacts
LRANGE contacts:user:1 0 9
Use Case 3: Round-Robin Scheduling
# Task list
LPUSH tasks "task1" "task2" "task3"
# Round-robin: pop task, process it, then put it back at the tail
RPOPLPUSH tasks tasks
"task1" # Process task1
# Next poll will get task2
Use Case 4: Capped Log
# Add a log entry
LPUSH log:app "log message"
# Keep the most recent 1000 log entries
LTRIM log:app 0 999
# View recent logs
LRANGE log:app 0 99
List Performance Optimization
1. Avoid Middle Operations
# ❌ Poor performance: insert or delete in the middle
LINSERT mylist BEFORE "middle" "new"
LREM mylist 1 "middle"
# ✅ Good performance: only operate at head and tail
LPUSH mylist "new"
LPOP mylist
2. Avoid Large Lists
# ❌ List too large
LLEN mylist
(integer) 1000000
# ✅ Use LTRIM to limit length
LTRIM mylist 0 9999
3. Fetch in Batches with LRANGE
# ❌ Fetch a huge range at once
LRANGE mylist 0 -1
# ✅ Fetch in batches
LRANGE mylist 0 99
LRANGE mylist 100 199
4. Choose the Right Data Structure
| Requirement | Recommended Data Structure |
|---|---|
| Queue/Stack | List |
| Latest N items | List + LTRIM |
| Pagination | List + LRANGE |
| Deduplicated list | Set or Sorted Set |
| Weighted sorting | Sorted Set |
List Limitations
1. Slow Element Lookup
# Finding a specific value requires traversing the entire list
LINDEX mylist 500000 # O(N) operation, very slow
2. Slow Middle Operations
# Inserting or deleting in the middle requires shifting elements
LINSERT mylist BEFORE "middle" "new" # O(N)
3. Cannot Find Index by Value
Redis does not provide a command to find the index of a value by its content. This must be implemented at the application level.
❓ FAQ
LINDEX mylist 0 is equivalent to LRANGE mylist 0 0.📖 Summary
- LINDEX gets element by index, LSET sets element by index
- LINSERT inserts before or after a pivot (O(N) performance)
- LREM removes elements by value, with control over count and direction
- RPOPLPUSH moves elements, used for circular queues and backup queues
- BRPOPLPUSH blocking move, used for reliable message queues
- Advanced list applications: pagination, recent contacts, round-robin scheduling
- Performance optimization: avoid middle operations, limit list length, batch fetch
📝 Exercises
- Index operations: Create a list, use LINDEX to get elements at different positions, use LSET to modify elements
- Insert and delete: Use LINSERT to insert in the middle, use LREM to remove elements by value
- Element movement: Use RPOPLPUSH to implement a circular queue for task round-robin
- Pagination: Create a list with 20 elements and implement pagination with 5 items per page
Next Lesson
In the next lesson, we will learn Redis Sets (Part 1), covering basic set operations.



