跳转到内容

Redis List 类型


List 是 Redis 中的有序、可重复的字符串列表,底层是双端链表结构,支持从两端高效插入和弹出,时间复杂度 O(1)。

List 结构示意(双端队列):
key = "msg:queue"
LEFT ←── [msg5] [msg4] [msg3] [msg2] [msg1] ──→ RIGHT
↑ ↑
LPUSH/LPOP RPUSH/RPOP
特点说明
有序元素按插入顺序存储,支持按索引访问
可重复允许存储相同元素
双端操作头部和尾部均支持 O(1) 插入/弹出
阻塞弹出BLPOP 支持阻塞等待,适合消息队列
上限单个 List 最多 2^32 - 1 个元素
Terminal window
# 插入
LPUSH list a b c # 从左插入,最终顺序:c b a(后插的在左边)
RPUSH list d e # 从右插入,最终顺序:c b a d e
LINSERT list BEFORE "a" "x" # 在元素 a 前插入 x
# 弹出
LPOP list # 从左弹出,返回元素
RPOP list # 从右弹出,返回元素
LPOP list 2 # 从左弹出 2 个(Redis 6.2+)
# 阻塞弹出(消息队列核心命令)
BLPOP list 10 # 阻塞等待,最多 10 秒,有消息立即返回
BRPOP list 10 # 从右端阻塞弹出
Terminal window
LRANGE list 0 -1 # 获取全部元素(-1 表示最后一个)
LRANGE list 0 4 # 获取前 5 个元素
LINDEX list 0 # 获取指定下标元素(0 = 第一个,-1 = 最后一个)
LLEN list # 获取列表长度
Terminal window
LSET list 0 "new" # 修改指定下标的值
LREM list 2 "a" # 从左删除 2 个值为 "a" 的元素(负数从右删)
LTRIM list 0 99 # 裁剪,只保留下标 0~99 的元素(常用于限制列表长度)
命令说明复杂度
LPUSH / RPUSH左/右插入O(1)
LPOP / RPOP左/右弹出O(1)
BLPOP / BRPOP阻塞弹出O(1)
LRANGE key s e范围查询O(N)
LINDEX key i下标查询O(N)
LLEN key列表长度O(1)
LREM key n val删除元素O(N)
LTRIM key s e裁剪列表O(N)
List 底层编码
├── listpack(紧凑列表)
│ → 元素数 ≤ 128 且每个元素长度 ≤ 64 字节
│ → 内存紧凑,连续存储
└── quicklist(快速列表)
→ 超过阈值后自动升级
→ 由多个 listpack 节点组成的双向链表
→ 兼顾内存效率与操作性能
@Autowired
private StringRedisTemplate redisTemplate;
ListOperations<String, String> listOps = redisTemplate.opsForList();
// 插入
listOps.leftPush("queue", "task1");
listOps.rightPush("queue", "task2");
listOps.rightPushAll("queue", List.of("task3", "task4"));
// 弹出
String task = listOps.leftPop("queue");
String taskWithTimeout = listOps.leftPop("queue", 5, TimeUnit.SECONDS); // 阻塞 5 秒
// 查询
List<String> all = listOps.range("queue", 0, -1);
String first = listOps.index("queue", 0);
Long size = listOps.size("queue");
// 裁剪(保留最新 100 条)
listOps.trim("news:latest", 0, 99);
@Service
@RequiredArgsConstructor
public class SimpleQueue {
private final StringRedisTemplate redisTemplate;
private static final String QUEUE_KEY = "msg:queue";
// 生产者:推入消息
public void push(String message) {
redisTemplate.opsForList().rightPush(QUEUE_KEY, message);
}
// 消费者:阻塞拉取(无消息时等待,不轮询)
public String pop() {
return redisTemplate.opsForList()
.leftPop(QUEUE_KEY, 10, TimeUnit.SECONDS);
}
}
@Service
@RequiredArgsConstructor
public class FeedService {
private final StringRedisTemplate redisTemplate;
private static final int MAX_FEED_SIZE = 500;
// 发布动态:插入头部,保持最新在前
public void publish(Long userId, String content) {
String key = "feed:" + userId;
redisTemplate.opsForList().leftPush(key, content);
// 只保留最新 500 条
redisTemplate.opsForList().trim(key, 0, MAX_FEED_SIZE - 1);
}
// 分页获取动态
public List<String> getFeeds(Long userId, int page, int size) {
String key = "feed:" + userId;
long start = (long)(page - 1) * size;
long end = start + size - 1;
return redisTemplate.opsForList().range(key, start, end);
}
}
队列(FIFO):RPUSH 入队 + LPOP 出队
┌─────────────────────────────────┐
│ RPUSH ──▶ [e][d][c][b][a] ◀── LPOP │
└─────────────────────────────────┘
栈(LIFO):LPUSH 入栈 + LPOP 出栈
┌─────────────────────────────────┐
│ LPUSH ──▶ [c][b][a] ◀── LPOP │
└─────────────────────────────────┘
场景方案关键命令
异步任务队列RPUSH 入队 + BLPOP 阻塞消费BLPOP
最新消息列表LPUSH + LTRIM 限长LTRIM
历史记录RPUSH + LRANGE 分页LRANGE
操作日志栈LPUSH + LPOP 后进先出LPOP