版权声明: 转载请注明出处!本文采用 知识共享 署名-非商业性使用-禁止演绎 4.0 国际许可协议
前言
今天学习的这两个命令是操作 lists 类型键的最后两个命令,也是 Redis 中比较长的两个命令了,看名字就可以看出来, RPOPLPUSH 命令就是 RPOP 和 LPUSH 命令的组合,而 BRPOPLPUSH 命令是 RPOPLPUSH 命令的阻塞版本,具体的作用我们接下来实验一下。
这篇笔记中的2个命令分别是 RPOPLPUSH 、 BRPOPLPUSH ,可以参考:
- 《Redis每日一练(22):LPOP、RPUSH和RPOP命令》 中的 RPOP 命令
- 《Redis每日一练(21):LPUSH和LRANGE命令》 中的 LPUSH 命令
- 《Redis每日一练(26):BLPOP和BRPOP命令》 中的 BRPOP 命令
RPOPLPUSH
- 最早出现版本:1.2.0
- 时间复杂度:O(1)
- 命令参数:RPOPLPUSH source destination
- 操作类型:lists
- 官方文档
作用
本来看这个命令的时候感觉挺麻烦的,本来名字就很长,文档的内容也不短,还是一个组合命令,但是在仔细看了这个命令的文档以后,忽然发现这个命令也挺简单的,本质上就是从一个列表尾部取出一个元素放到一个列表的头部,这两个列表可以是两个不同的列表,也可以是同一个列表。
这个命令有什么用呢?因为这是一个组合命令,可以实现一个请求就将一个队列中的元素移动到另一个列表中,而使用 RPOP 命令和 LPUSH 命令因为使用了两种命令,就可能因为网络或者其他问题而造成这种移动操作中断,所以使用 RPOPLUSH 命令更加可靠。
因为这个命令操作目标的是列表,所以也会有一些列表的要求和限制,正常操作下该命令返回移动的元素值,还有一些报错的情况我们做实验看一下。
练习
如果原列表不存在,那就无法实现 RPOP 操作了,直接返回nil:
127.0.0.1:6379> LRANGE alist 0 -1
(empty list or set)
127.0.0.1:6379> LRANGE blist 0 -1
(empty list or set)
127.0.0.1:6379> RPOPLPUSH alist blist
(nil)
127.0.0.1:6379>
如果原列表指定的键实际上不是一个列表类型,那么就会像 RPOP 命令一下给出报错信息:
127.0.0.1:6379> SET name albert
OK
127.0.0.1:6379> RPOPLPUSH name blist
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
如果原列表中包含元素,而目标列表位置指定的键不是列表类型同样会报错:
127.0.0.1:6379> TYPE name
string
127.0.0.1:6379> RPOPLPUSH alist name
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
如果原列表中包含元素,而目标列表不存在,则会创建一个目标列表,并将元素移动过去:
127.0.0.1:6379> LRANGE alist 0 -1
1) "5"
2) "test"
3) "3"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> LRANGE blist 0 -1
(empty list or set)
127.0.0.1:6379> RPOPLPUSH alist blist
"a"
127.0.0.1:6379> LRANGE alist 0 -1
1) "5"
2) "test"
3) "3"
4) "c"
5) "b"
127.0.0.1:6379> LRANGE blist 0 -1
1) "a"
127.0.0.1:6379>
如果原列表和目标列表是同一个,那么就会从列表右端取出元素插入到左端:
127.0.0.1:6379> LRANGE alist 0 -1
1) "5"
2) "test"
3) "3"
4) "c"
5) "b"
127.0.0.1:6379> RPOPLPUSH alist alist
"b"
127.0.0.1:6379> LRANGE alist 0 -1
1) "b"
2) "5"
3) "test"
4) "3"
5) "c"
127.0.0.1:6379>
BRPOPLPUSH
- 最早出现版本:2.2.0
- 时间复杂度:O(1)
- 命令参数:BRPOPLPUSH source destination timeout
- 操作类型:lists
- 官方文档
作用
BRPOPLPUSH 命令是 RPOPLPUSH 命令的阻塞版本,这是学习 BLPOP 命令和 BRPOP 命令之后的第三个阻塞命令,功能与 RPOPLPUSH 基本相同,只是有时会出现阻塞状态。
当原列表中包含元素时该命令 与 RPOPLPUSH 表现相同,当原列表中不包含元素时该命令会阻塞连接,直到超时时间到了或者原列表中被插入了新元素。
练习
启动A连接将一个不存在的空的 clist 作为原列表执行 BRPOPLPUSH 操作,会立即进入阻塞状态:
127.0.0.1:6379> GET clist
(nil)
127.0.0.1:6379> BRPOPLPUSH clist blist 0
启动连接B向列表 clist 中插入元素,查看列表内容:
127.0.0.1:6379> LPUSH clist movedata
(integer) 1
127.0.0.1:6379> LRANGE clist 0 -1
(empty list or set)
127.0.0.1:6379>
插入元素后查看列表元素为空,返回到A连接看到原来的 BRPOP 命令已经返回:
127.0.0.1:6379> BRPOPLPUSH clist blist 0
"movedata"
(96.06s)
127.0.0.1:6379> LRANGE blist 0 -1
1) "movedata"
2) "a"
127.0.0.1:6379>
总结
- RPOPLPUSH 命令是 RPOP 命令和 LPUSH 命令的组合,会从原列表尾部元素移动到目标列表的头部。
- BRPOPLPUSH 命令是 RPOPLPUSH 命令 的阻塞版本,当原列表中没有元素时会阻塞连接直到超时时间到或者原列表中被其他连接插入了新元素。
2019-12-15 21:40:48