列表类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储2的32次方-1个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色。
列表类型有两个特点:
- 列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。
- 列表中的元素可以是重复的。
1. 添加操作
(1) 从右边插入元素
rpush key element [element ...]
下面从右向左插入元素a、b、c:
192.168.211.131:7002> rpush list:1 c b a
(integer) 3
(2) 从左边插入元素
lpush key element [element ...]
下面从左向右插入元素e、f、g
192.168.211.131:7002> lpush list:1 e f g
(integer) 6
(3) 向某个元素前或者后插入元素
linsert key BEFORE|AFTER pivot element
linsert命令会从列表中找到等于pivot的元素,在其前(before)或者后(after)插入一个新的元素value,例如下面操作会在列表的元素c前插入d:
192.168.211.131:7002> linsert list:1 before c d
(integer) 7
2. 查找
(1) 获取执行范围内的元素列表
lrange key start stop
lrange操作会获取列表执行索引范围所有的元素。索引下标有两个特点:第一,索引下标从左到右分别是0到N-1,但是从右到左分别是-1到-N。第二,lrange中的end选项包含了自身,这个和很多编程语言不包含end不太相同,例如想获取列表的第2到第4个元素,可以执行如下操作:
192.168.211.131:7002> lrange list:1 1 3
1) "f"
2) "e"
3) "d"
(2) 获取列表指定索引下的元素
lindex key index
例如获取当前列表最后一个元素为a:
192.168.211.131:7002> lindex list:1 -1
"a"
(3) 获取列表长度
llen key
例如获取list:1的长度为7:
192.168.211.131:7002> llen list:1
(integer) 7
3. 删除
(1) 从列表左侧弹出元素
lpop key
下面操作将列表最左侧的元素g弹出,弹出后列表变为f、e、d、c、b、a:
192.168.211.131:7002> lpop list:1
"g"
192.168.211.131:7002> lrange list:1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
(2) 从列表右侧弹出
rpop key
它的使用方法和lpop是一样的,只不过从列表右侧弹出。
(3) 删除指定元素
lrem key count value
lrem命令会从列表中找到等于value的元素进行删除,根据count的不同分为三种情况:
- count>0,从左到右,删除最多count个元素。
- count<0,从右到左,删除最多count绝对值个元素。
- count=0,删除所有。
向列表list:1从左向右插入5个1,那么当前列表变为“1 1 1 1 1 f e d c b a“,下面操作将从列表左边开始删除5个1:
192.168.211.131:7002> lpush list:1 1 1 1 1 1
(integer) 11
192.168.211.131:7002> lrem list:1 5 1
(integer) 5
192.168.211.131:7002> lrange list:1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
(4) 按照索引范围修剪列表
ltrim key start end
下面操作只会保留列表list:1第2个到第4个元素:
192.168.211.131:7002> ltrim list:1 1 3
OK
192.168.211.131:7002> lrange list:1 0 -1
1) "e"
2) "d"
3) "c"
4. 修改
修改指定索引下标的元素
lset key index element
下面操作会将列表list:1中的第3个元素设置为a:
192.168.211.131:7004> lrange list:1 0 -1
1) "e"
2) "d"
3) "a"
5. 阻塞操作
阻塞式弹出如下
blpop key [key ...] timeout
brpop key [key ...] timeout
blpop和brpop是lpop和rpop的阻塞版本,它们除了弹出方向不通,使用方法基本相同,所以下面以brpop命令进行说明,brpop命令包含2个参数:
- key [key ...]:多个列表的键。
- timeout:阻塞时间(单位:秒)。
(1) 列表为空:如果timeout=3,那么客户端要等到3秒后返回,如果timeout=0,那么客户端一直阻塞等下去:
192.168.211.131:7004> brpop list:2 10
(nil)
(10.08s)192.168.211.131:7003> brpop list:2 0
…一直阻塞…
如果此期间添加了数据element1,客户端立即返回:
192.168.211.131:7003> brpop list:2 10
1) "list:2"
2) "1"
(2.70s)
(2) 列表不为空:客户端会立即返回。
192.168.211.131:7004> brpop list:1 1
1) "list:1"
2) "1"
在使用brpop时,有两点需要注意。
第一点,如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立即返回:
客户端1
192.168.211.131:6379> brpop list:1 list:2 list:3 0
…阻塞…
此时另一个客户端分别向list:2和list:3插入元素:
客户端2
192.168.211.131:6379> lpush list:2 1
(integer) 1
192.168.211.131:6379> lpush list:3 1
(integer) 1
客户端会立即返回list:2中的element2,因为list:2最先有可以弹出的元素:
客户端1
192.168.211.131:6379> brpop list:1 list:2 list:3 0
1) "list:2"
2) "1"
(12.28s)
第二点,如果多个客户端对同一个键执行brpop,那么最先执行brpop命令的客户端可以获取到弹出的值。
客户端1
192.168.211.131:6379> brpop list:1 0
…阻塞…
客户端2
192.168.211.131:6379> brpop list:1 0
…阻塞…
客户端3
192.168.211.131:6379> brpop list:1 0
…阻塞…
此时另一个客户端lpush一个元素到list:1列表中:
192.168.211.131:6379> lpush list:1 1
(integer) 1
那么客户端1会最先获取到元素,因为客户端1最先执行的brpop,而客户端2和客户端3会继续阻塞:
客户端1
192.168.211.131:6379> brpop list:1 0
1) "list:1"
2) "1"
(27.09s)