Skip to content

Redis - 列表

Redis 列表是字符串的有序集合,按插入顺序排序。它们被实现为链表(Linked Lists),这使得即使对于包含数百万元素的列表,向列表的头部(左侧)或尾部(右侧)添加新元素也速度非常快。

像 LPUSH(添加到头部)和 RPOP(从尾部移除)这样的关键操作是 O(1),这意味着它们的速度与列表的大小无关。列表的最大长度为 2^32 - 1 个元素(超过 40 亿)。

实际示例:一个简单的任务队列

Section titled “实际示例:一个简单的任务队列”

列表非常适合实现生产者-消费者模式,例如任务队列。一个“生产者”(producer)应用程序将任务推送到列表中,一个或多个“工作者”(worker)应用程序从列表中拉取任务进行处理。

生产者使用 LPUSH 将新任务添加到名为 task_queue 的列表头部。我们将使用 JSON 字符串来表示结构化任务。

# Producer adds three tasks to the queue
# 生产者向队列添加三个任务
redis> LPUSH task_queue '{"type":"send_email", "recipient":"user1@example.com"}'
(integer) 1
redis> LPUSH task_queue '{"type":"generate_report", "report_id":"xyz-123"}'
(integer) 2
redis> LPUSH task_queue '{"type":"process_image", "image_id":987}'
(integer) 3

工作者可以使用 RPOP 从列表的尾部获取最旧的任务。然而,一个更好的方法是使用阻塞命令 BRPOP。它原子性地移除并返回最后一个元素,但如果列表为空,它将阻塞连接,直到有新元素可用或达到超时。这比不断轮询列表效率高得多。

# Worker asks for a task, blocking for up to 10 seconds if none are available.
# 工作者请求一个任务,如果没有可用任务则阻塞最长 10 秒。
# It receives the first task that was pushed (FIFO - First-In, First-Out).
# 它接收第一个被推送的任务(FIFO - 先进先出)。
redis> BRPOP task_queue 10
1) "task_queue"
2) "{\"type\":\"send_email\", \"recipient\":\"user1@example.com\"}"
# Worker asks again and gets the next task
# 工作者再次请求并获得下一个任务
redis> BRPOP task_queue 10
1) "task_queue"
2) "{\"type\":\"generate_report\", \"report_id\":\"xyz-123\"}"
# If the worker asks again and the queue is empty, the command will wait.
# 如果工作者再次请求且队列为空,命令将等待。
# After 10 seconds, if no producer has pushed a new task, it will return (nil).
# 10 秒后,如果没有生产者推送新任务,它将返回 (nil)。
redis> BRPOP task_queue 10
(nil)
(10.00s)
  • 有上限的列表(Capped Lists):对于存储最新日志或活动等用例,使用 LPUSH 添加项目,并使用 LTRIM 定期将列表裁剪到固定大小。这可以防止无限制的内存增长。
  • 避免列表中间操作:像 LINDEX(按索引获取元素)和 LINSERT(按索引插入元素)这样的命令速度较慢(O(N))。它们需要从列表头部或尾部遍历列表。对于高性能应用程序,请坚持使用头部/尾部操作(LPUSH、RPUSH、LPOP、RPOP)。
  • 对于可靠队列,考虑 Streams:虽然列表非常适合简单的队列,但它们缺乏消息确认和消费者组等功能。如果你不能承受丢失单个任务的风险(例如,如果工作者在 RPOP 之后但在完成之前崩溃),则应使用更强大的 Redis Streams 数据结构。
命令描述
LPUSH key element [element …]将一个或多个元素前置到列表的头部(左侧)。
RPUSH key element [element …]将一个或多个元素追加到列表的尾部(右侧)。
LPOP key [count]移除并返回列表的第一个元素(从头部)。
RPOP key [count]移除并返回列表的最后一个元素(从尾部)。
BLPOP key [key …] timeoutLPOP 的阻塞版本。阻塞直到有元素可用或超时发生。
BRPOP key [key …] timeoutRPOP 的阻塞版本。可靠工作者队列的首选命令。
LLEN key获取列表的长度。
LRANGE key start stop从列表中获取一个元素范围。在非常长的列表上使用时要谨慎。
LTRIM key start stop将列表裁剪到指定的范围,移除范围之外的元素。