Redis 里面的List 既是一个列表也是一个双向链表, 除了可以通过序号进行元素操作之外, 还可以对其进行push/pop操作, 以实现栈和队列的功能.list 中的元素是可以重复的.redis 的列表是非常强大的,可以实现列表,栈,固定长度列表,环形列表等结构.
1. 常用命令
以下API 只适用于结构为List的key, 否则会报错.
1.1 非阻塞式命令
- Redis 的list 不只是list,可以作为队列,栈, 双端队列等.
操作命令 | 描述 | 返回值 |
---|---|---|
lpush/rpush $key $item [ $item…] | 从列表左侧或右侧压入一到多个元素, 支持批量操作 | 如果list 不存在,则会先自动创建一个list, 返回list的总个数 |
lpushx/rpushx | 从已存在列表左侧或右侧压入一个元素,不支持批量操作 | 如果list 存在返回list 元素总个数,否则返回nil |
lpop/rpop $key | 从列表左侧/右侧弹出一个元素 | 如果list 不存在或list 元素为空,则返回nil; 否则返回对应的元素 |
lrange $key $start $end | 返回list 中指定范围的多个元素,但不会删除元素 | 左侧元素下表从0 开始, 右侧元素下表从-1 开始. |
ltrim $key $start $end | 截取list , 只保留指定范围的元素 | 常与lpush/rpush 配合使用以实现固定长度的集合 |
lindex $key $index | 列表的标准获取元素方式,通过元素索引获取元素 | 索引支持正负数, 当索引大于列表长度或列表不存在时返回nil |
lset $key $index $value | 替换列表指定下标的元素 | 索引的可为正负数, 当索引超过了列表长度会报错 |
llen $key | 获取列表元素个数 | 当列表不存在时返回0,否则返回列表中元素个数 |
lrem $key $conunt $value | 移除列表中conunt个值为value的元素 | conut 值的正负数决定了从左开始数还是从右开始数 |
linsert $key before/after $pivot $value | 从列表左侧开始,向第一个匹配到的元素前面或者后面插入一个元素. | 正常返回列表的个数 |
rpoplpush $source $destination | 从源列表右侧弹出一个元素并从目标列表左侧压入 | 返回移动的元素. 可以实现环式列表 |
1.2 阻塞式命令
- 阻塞式命令可以实现生产者消费者模式, 一个消息只能被一个消费者消费一次
- 阻塞式命令主要用于当列表为空时, 命令会处于等待状态, 当队列中有数据时返回, 或者等待时间超过了设置的超时时间后退出.
操作命令 | 描述 | 返回值 |
---|---|---|
blpop/brpop k e y [ key [ key[key …] $timeoutSecs | 阻塞式从左侧/右侧弹出一个元素, 可同时监听多个key | 返回key 和 元素的组合, timeout 为等待时间,超时后结束等待返回nil, 为0时表示永远等待 |
brpoplpush $source $destination $timeoutSecs | 阻塞式的从源队列中右侧移除一个元素并从左侧压入目标队列,同brpoplpush 相似 |
2. 非阻塞式命令详解
2.1 lpush/rpush
- lpush 是从list 左侧压入元素, 当批量压入元素的时候, 元素是依次向左压人, 因此list 中存放顺序和书写相反
- rpush 是从list 右侧压入元素, 当批量压入元素的时候, 元素是依次向右压入, 因此list中存放顺序和书写相同
# 从左侧压入五个元素
127.0.0.1:6379> lpush numbers 1 2 3 4 5
(integer) 5
# 从右侧压入五个元素
127.0.0.1:6379> rpush numbers 5 4 3 2 1
(integer) 10
# 获取list 所有元素
127.0.0.1:6379> lrange numbers 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
2.2 lpushx/rpushx
从列表左侧或右侧压入一个元素, 但
# 验证chars 不存在
127.0.0.1:6379> keys *
1) "numbers"
# 向不存在的列表 插入元素,返回0, 也不会自动创建列表
127.0.0.1:6379> lpushx chars a
(integer) 0
# 创建列表
127.0.0.1:6379> lpush chars a
(integer) 1
127.0.0.1:6379> keys *
1) "chars"
2) "numbers"
# 向已存在列表压入元素, 返回列表的元素总个数
127.0.0.1:6379> lpushx chars b
(integer) 2
127.0.0.1:6379> lpushx chars c
(integer) 3
# 查看list 元素存储情况
127.0.0.1:6379> lrange chars 0 -1
1) "c"
2) "b"
3) "a
2.3 lpop/rpop
从列表左侧/右侧弹出一个元素, 返回弹出的元素. 此元素会在list 中被删除.
# 弹出list 最左侧的元素
127.0.0.1:6379> lpop numbers
"5"
# 弹出list 最右侧的元素
127.0.0.1:6379> rpop numbers
"1"
# 弹出就相当于删除元素
127.0.0.1:6379> lrange numbers 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "5"
6) "4"
7) "3"
8) "2"
2.4 lrange
- 从列表中获取指定范围的元素列表,只是获取而不删除.
- 元素下标从0 开始支持负数, 左侧第一个元素下标为0, 右侧元素下表为-1.
- 获取元素范围是一个左闭右闭的区间
- 索引的正负数取决于从左还是从右数
# 获取list 所有元素, -1 代表末尾元素
127.0.0.1:6379> lrange numbers 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "5"
6) "4"
7) "3"
8) "2"
# 获取list 部分元素, 从左侧数, 第一到第四个元素
127.0.0.1:6379> lrange numbers 0 3
1) "4"
2) "3"
3) "2"
4) "1"
# 获取list 部分元素, 从右侧数, 获取第1到第三个元素
127.0.0.1:6379> lrange numbers -3 -1
1) "4"
2) "3"
3) "2"
2.5 ltrim
- 裁剪列表, 只保留筛选范围的元素.
- 索引也支持正负数,正负数只表示从列表左侧还算从右侧开始数
- 常与lpush/rpush 配合使用来当需要一个固定长度的list的时候.比如绑定 lpush 和 ltrim 0 99 这两条命令,就可以保证list 一直是最多只有100 个元素的列表.
# 查看原来的元素
127.0.0.1:6379> lrange numbers 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "5"
6) "4"
7) "3"
8) "2"
# 对列表进行截取,只保留从左到右的前四个元素.
127.0.0.1:6379> ltrim numbers 0 3
OK
# 查看列表生育元素
127.0.0.1:6379> lrange numbers 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
2.6 lindex
- 按索引获取元素, 索引下表可以为正负数.
- 索引正负数只表示从左/从右数
127.0.0.1:6379> lrange numbers 0 -1
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
# 正向索引获取元素
127.0.0.1:6379> lindex numbers 0
"0"
# 逆向索引获取元素
127.0.0.1:6379> lindex numbers -1
"5"
# 索引下标超出列表长度之后, 返回nil
127.0.0.1:6379> LINDEX numbers 100
(nil)
2.7 lset
× 替换指定索引的元素,数组下标从0开始且支持负数
127.0.0.1:6379> lrange numbers 0 -1
1) "0"
2) "1"
3) "2"
4) "3"
# 正向索引替换
127.0.0.1:6379> lset numbers 2 a
OK
# 逆向索引替换
127.0.0.1:6379> lset numbers -1 b
OK
127.0.0.1:6379> lrange numbers 0 -1
1) "0"
2) "1"
3) "a"
4) "b"
# 索引超出了列表长度会报错
127.0.0.1:6379> lset numbers 10 10
(error) ERR index out of range
# 列表不存在也会报错
127.0.0.1:6379> lset numbers2 10 10
(error) ERR no such key
2.8 llen
- 获取列表元素个数,当列表不存在时返回0
127.0.0.1:6379> llen numbers
(integer) 6
2.9 lrem
从列表中删除多个相同的元素,对于count 取值
- count > 0: 从头往尾移除$count个值为 value 的元素。
- count < 0: 从尾往头移除$count个值为 value 的元素。
- count = 0: 移除所有值为 value 的元素。
# 列表原始元素
127.0.0.1:6379> lrange chars 0 -1
1) "0"
2) "a"
3) "1"
4) "a"
5) "2"
6) "a"
7) "3"
8) "a"
9) "4"
10) "a"
11) "5"
12) "a"
# 从左侧删除1个a 元素
127.0.0.1:6379> lrem chars 1 a
(integer) 1
127.0.0.1:6379> lrange chars 0 -1
1) "0"
2) "1"
3) "a"
4) "2"
5) "a"
6) "3"
7) "a"
8) "4"
9) "a"
10) "5"
11) "a"
# 从右侧删除2个a元素
127.0.0.1:6379> lrem chars -2 a
(integer) 2
127.0.0.1:6379> lrange chars 0 -1
1) "0"
2) "1"
3) "a"
4) "2"
5) "a"
6) "3"
7) "a"
8) "4"
9) "5"
# 删除所有的a元素
127.0.0.1:6379> lrem chars 0 a
(integer) 3
127.0.0.1:6379> lrange chars 0 -1
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
2.10 linsert
从列表左侧开始,向第一个匹配到的元素前面或者后面插入一个元素.
# 创建列表,有重复元素a,b
127.0.0.1:6379> lrange chars 0 -1
1) "a"
2) "b"
3) "a"
4) "b"
5) "c"
# 在元素a 前插入1, 只会在从左开始数的第一个元素a前插入1
127.0.0.1:6379> linsert chars before a 1
(integer) 6
# 在元素b 后插入元素2, 只会在从左到右的第一个元素后面插入2
127.0.0.1:6379> linsert chars after b 2
(integer) 7
127.0.0.1:6379> lrange chars 0 -1
1) "1"
2) "a"
3) "b"
4) "2"
5) "a"
6) "b"
7) "c"
2.11 rpoplpush
从源列表右侧弹出一个元素并从目标列表左侧压入, 返回移动的元素. 可以实现环式列表.
# 原始列表
127.0.0.1:6379> lrange chars 0 -1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> lrange numbers 0 -1
1) "0"
2) "1"
3) "2"
# 从chars 列表右侧弹出一个元素并从左侧压入numbers 列表
127.0.0.1:6379> rpoplpush chars numbers
"c"
127.0.0.1:6379> lrange numbers 0 -1
1) "c"
2) "0"
3) "1"
4) "2"
127.0.0.1:6379> lrange chars 0 -1
1) "a"
2) "b"
# 实现环式列表
127.0.0.1:6379> rpoplpush chars chars
"b"
127.0.0.1:6379> lrange chars 0 -1
1) "b"
2) "a"
3. 阻塞式命令详解
3.1 blpop/brpop
# 返回值为key 和 弹出元素的组合
127.0.0.1:6379> blpop numbers 1000
1) "numbers"
2) "0"
(30.67s)
# 阻塞超时后自动结束阻塞状态
127.0.0.1:6379> blpop numbers 1
(nil)
(1.06s)
3.2 brpoplpush
127.0.0.1:6379> brpoplpush numbers chars 1000
"0"
(6.19s)