*Redis LMOVE 命令

LMOVE 原子地从源列表中弹出最左或最右的元素,并推入目标列表的最左或最右端。是 RPOPLPUSH 的泛化版本,支持 LL、LR、RL、RR 四种方向组合。


*语法

LMOVE source destination <LEFT | RIGHT> <LEFT | RIGHT>

*参数说明

参数 类型 必填 说明
source String 源列表键名
destination String 目标列表键名,可以与 source 相同
LEFT / RIGHT (第一个) Enum 从源列表弹出元素的位置:LEFT(左端/头部)或 RIGHT(右端/尾部)
LEFT / RIGHT (第二个) Enum 向目标列表推入元素的位置:LEFT 或 RIGHT

方向组合说明: - LEFT LEFT:LPOP + LPUSH(从源左端弹出,压入目标左端) - LEFT RIGHT:LPOP + RPUSH(从源左端弹出,压入目标右端) - RIGHT LEFT:RPOP + LPUSH(从源右端弹出,压入目标左端) - RIGHT RIGHT:RPOP + RPUSH(从源右端弹出,压入目标右端)


*返回值

  • String / Bytes:被移动的元素值
  • Nil:源列表不存在或为空时返回 (nil)
  • Error:source 或 destination 不是列表类型

*时间复杂度

O(1)

*

*示例

*基本用法(循环队列)

> RPUSH mylist "one" "two" "three"
(integer) 3
> LMOVE mylist mylist RIGHT LEFT
"three"
> LRANGE mylist 0 -1
1) "three"
2) "one"
3) "two"

*列表间移动

> RPUSH queue "job1" "job2"
(integer) 2
> LMOVE queue processing LEFT LEFT
"job1"
> LRANGE processing 0 -1
1) "job1"

*右端弹出左端推入(原 RPOPLPUSH 行为)

> RPUSH src "a" "b" "c"
(integer) 3
> LMOVE src dest RIGHT LEFT
"c"
> LRANGE dest 0 -1
1) "c"

*空列表

> LMOVE empty dest LEFT LEFT
(nil)

*常见错误

错误 原因 解决
ERR wrong number of arguments for 'lmove' command 参数不足 确保提供 source、destination 和两个方向参数
WRONGTYPE Operation against a key holding the wrong kind of value source 或 destination 不是列表类型 检查键的数据类型,或使用 TYPE 命令确认

*最佳实践

  • RIGHT LEFT 组合等价于已废弃的 RPOPLPUSH,可用于实现可靠的队列(元素在传输过程中不丢失)
  • 原子操作保证元素要么在源列表,要么在目标列表,不会丢失,适合需要可靠传输的场景
  • source 和 destination 可以是同一个键,实现列表内的元素轮转
  • 需要阻塞等待时,使用 BLMOVE(Redis 6.2+)替代,支持超时参数

*FAQ

Q1: LMOVE 和 RPOPLPUSH 有什么区别? A: RPOPLPUSH 是固定的 "源右端弹出、目标左端推入";LMOVE 支持四种方向组合。RPOPLPUSH 已被标记为废弃,建议使用 LMOVE 的 RIGHT LEFT 组合替代。

Q2: LMOVE 会删除源列表吗? A: 如果移动后源列表为空,Redis 会自动删除该 key(这是 List 类型的标准行为)。

Q3: source 和 destination 相同时会发生什么? A: LMOVE 允许 source 和 destination 为同一个键,实现列表内元素的轮转。例如 LMOVE mylist mylist RIGHT LEFT 将最后一个元素移到最前面。

Q4: 有阻塞版本的 LMOVE 吗? A: 有。Redis 6.2 引入了 BLMOVE,增加了 timeout 参数,当源列表为空时会阻塞等待直到有元素或超时。