*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 参数,当源列表为空时会阻塞等待直到有元素或超时。