Lists trong Redis là một tập hợp các giá trị có thứ tự, được sắp xếp theo thứ tự thêm vào. Đây là cấu trúc dữ liệu lý tưởng cho queue, stack, và activity feeds.
Lists là gì?
Redis List giống như một LinkedList — mỗi phần tử có link đến phần tử trước và sau. Điều này giúp:
- ✅ Thêm/xóa ở đầu hoặc cuối: O(1) — siêu nhanh
- ✅ Lấy phạm vi phần tử: O(S+N)
- ❌ Tìm kiếm phần tử: O(N) — chậm
Các lệnh cơ bản
| Lệnh | Độ phức tạp | Ghi chú |
|---|---|---|
| LPUSH / RPUSH / LPOP / RPOP | O(1) | Thao tác ở đầu/cuối list |
| LLEN | O(1) | Đếm số phần tử |
| LINDEX | O(N) | Truy cập theo index — tránh dùng trên list dài |
| LINSERT | O(N) | Chèn phần tử — phải duyệt list |
| LRANGE | O(S+N) | S=start, N=count phần tử |
| LREM | O(N+M) | N=list length, M=removed elements |
| BRPOP / BLPOP | O(N) | Blocking pop — N = số list theo dõi |
Thêm phần tử
# Thêm vào CUỐI list (Right)
RPUSH fruits "apple" "banana" "cherry"
# (integer) 3
# Thêm vào ĐẦU list (Left)
LPUSH fruits "mango"
# (integer) 4
# Thêm nhiều phần tử cùng lúc
RPUSH fruits "orange" "grape" "watermelon"
Lấy phần tử
# Lấy theo index (0-based)
LRANGE fruits 0 -1 # Tất cả phần tử
LRANGE fruits 0 2 # 3 phần tử đầu
LRANGE fruits -3 -1 # 3 phần tử cuối
# Lấy phần tử đầu/cuối
LINDEX fruits 0 # Phần tử đầu
LINDEX fruits -1 # Phần tử cuối
# Độ dài list
LLEN fruits
Xóa phần tử
# Lấy và XÓA phần tử đầu (Left Pop)
LPOP fruits
# "mango"
# Lấy và XÓA phần tử cuối (Right Pop)
RPOP fruits
# "watermelon"
# Xóa N phần tử có giá trị cụ thể
RPUSH nums 1 2 3 2 4 2 5
LREM nums 2 2 # Xóa 2 phần tử có giá trị "2" từ đầu
LREM nums -1 2 # Xóa 1 phần tử từ cuối
LREM nums 0 2 # Xóa tất cả phần tử có giá trị "2"
Queue với Lists (FIFO)
Sử dụng List như một message queue đơn giản:
# Producer: Thêm job vào queue
RPUSH queue:email "send_welcome_email:user123"
RPUSH queue:email "send_invoice:user456"
RPUSH queue:email "send_reminder:user789"
# Consumer: Lấy job từ queue
LPOP queue:email
# "send_welcome_email:user123"
LPOP queue:email
# "send_invoice:user456"
Blocking Pop (Chờ có job)
# BLPOP: Chờ tối đa 5 giây để lấy job
BLPOP queue:email 5
# Nếu có job: ["queue:email", "send_welcome:user123"]
# Nếu hết timeout: (nil)
# BLPOP trên nhiều queue
BLPOP queue:email queue:sms 0
# 0 = chờ vô hạn
Stack với Lists (LIFO)
# Push vào stack
RPUSH stack:undo "action1"
RPUSH stack:undo "action2"
RPUSH stack:undo "action3"
# Pop từ stack (LIFO)
RPOP stack:undo
# "action3"
RPOP stack:undo
# "action2"
Activity Feed
# Thêm hoạt động mới
LPUSH feed:user:1001 "{\"action\": \"like\", \"post\": 42}"
LPUSH feed:user:1001 "{\"action\": \"comment\", \"post\": 38}"
LPUSH feed:user:1001 "{\"action\": \"share\", \"post\": 55}"
# Lấy 10 hoạt động gần nhất
LRANGE feed:user:1001 0 9
# Giới hạn feed chỉ giữ 1000 mục
LTRIM feed:user:1001 0 999
LTRIM: Giới hạn kích thước
LTRIM giữ list không phình to vô hạn:
# Chỉ giữ 100 phần tử gần nhất
RPUSH logs "log1" "log2" ... "log200"
LTRIM logs 0 99
# Chỉ còn 100 phần tử đầu
# Pattern hay dùng: LPUSH + LTRIM
LPUSH recent:searches "redis tutorial"
LTRIM recent:searches 0 9 # Giữ 10 tìm kiếm gần nhất
Use Cases thực tế
1. Background Job Queue
# Web server: Thêm job xử lý ảnh
RPUSH jobs:image:resize "{\"image_id\": 123, \"size\": \"thumbnail\"}"
# Worker: Lấy và xử lý job
while True:
job = BLPOP jobs:image:resize, 0 # Chờ vô hạn
process_image(job)
2. Chat Messages
# Gửi tin nhắn
LPUSH chat:room:42 "{\"user\": \"Tan\", \"msg\": \"Hello!\"}"
# Lấy 50 tin nhắn gần nhất
LRANGE chat:room:42 0 49
# Giới hạn lịch sử chat
LTRIM chat:room:42 0 999
3. Recent Items
# Sản phẩm đã xem gần đây
LPUSH recent:views:user:1001 "product:555"
LTRIM recent:views:user:1001 0 19 # Giữ 20 sản phẩm
# Lấy danh sách
LRANGE recent:views:user:1001 0 -1
So sánh: Lists vs Streams
| Tiêu chí | Lists | Streams |
|---|---|---|
| Đơn giản | ✅ Rất đơn giản | ❌ Phức tạp hơn |
| Consumer Groups | ❌ Không hỗ trợ | ✅ Có |
| Message ID | ❌ Không có | ✅ Tự động tạo |
| Persistence | ⚠️ Phụ thuộc config | ✅ Tốt hơn |
| Use case | Queue đơn giản | Event streaming |

Best Practices
- Dùng LTRIM — Giới hạn list size, tránh memory leak
- Tránh LINDEX trên list dài — O(N) operation
- Dùng BRPOP cho queue — Blocking pop tiết kiệm CPU
- Pipeline khi batch — Gộp nhiều lệnh LPUSH thành batch
- Monitor list length — Dùng LLEN để theo dõi
Bước tiếp theo
Bạn đã nắm vững Lists trong Redis! Tiếp theo, chúng ta sẽ tìm hiểu về Hashes — cấu trúc dữ liệu lý tưởng để lưu trữ objects.