Redis数据结构-list

Redis数据结构-list

列表

列表的特点

  • 列表中的元素是有序的
  • 列表中的元素是可重复的

Redis数据结构-list

列表从两端插入弹出

命令

添加元素

从左边或右边插入元素

lpush key value [value ...]
rpush key value [value ...]
-------------------------------
> lpush leftkey q w e
3
> lrange leftkey  0 -1
e
w
q

从左查看所有元素

lrange key 0 -1
-------------------------
> lrange leftkey  0 -1
e
w
q

向某个元素前或者后插入元素

linsert key befor|after pivot value
-----------------------------------
> linsert leftkey before e java
5
> lrange leftkey  0 -1
java
e
w
q
r

返回结果是5,表示当前列表长度

查找

查找指定范围元素列表

lrange leftkey start end
-----------------------
> lrange leftkey  0 1
java
e

注意

  • 索引下标从左到右是0到N-1,但是从右到左是-1到-N.
  • lrange的end包含自身,左闭右闭

查找指定索引下标的元素

lindex key index
---------------------------
> lindex leftkey -1
r

返回列表最后一个元素

获取列表长度

llen key
--------------------
> llen leftkey
5

删除

从列表左侧弹出元素

lpop key
-------------------------
> lrange leftkey 0 -1
e
w
q
r
> lpop leftkey
e
> lrange leftkey 0 -1
w
q
r

相应的,从右侧弹出,rpop key

删除指定元素

lrem key count value
-------------------------------
> lpush testdup a a a b c a
6
> lrem testdup 2 a
2
> lrange testdup 0 -1
c
b
a
a
> lrem testdup 0 a
2
> lrange testdup 0 -1
c
b

lrem命令从列表中找到等于value的元素进行删除,根据count的不同分为三种情况

  • count > 0:从左到右,删除等于value的最多count个元素
  • count < 0:从右到左,删除等于value的最多count绝对值个元素
  • count = 0:删除所有元素

按照索引trim列表

ltrim key start end
-------------------------
> lrange testdup 0 -1
d
c
a
a
a
c
b
> ltrim testdup 1 3
OK
> lrange testdup 0 -1
c
a
a

阻塞操作

blpop key [key ...] timeout
brpop key [key ...] timeout
-----------------------------

空列表

如果对一个空列表执行该命令

> brpop newlist 3
(3s)
null

执行命令,会等待3s,然后返回null,如果timeout=0,客户端会一直等待下去。

直到阻塞期间,向列表中添加元素:

(客户端1)
> brpop testdup 0
(等待...直到客户端插入一个元素)
testdup
a
(客户端2)
> lpush testdup a
1

客户端会立即返回,不再阻塞等待

列表不为空

blpop立即返回

> lrange testdup 0 -1
b
a
> blpop testdup 3
(立刻返回)
testdup
b

注意:

  1. 阻塞等待多个key,brpop会从左至右遍历键,一旦有一个键能弹出来,客户端立即返回
> blpop key1 key2 key3 0
(等待...直到key1列表添加了元素,返回)
key1
a
  1. 如果多个客户端对一个key执行brpop,那么最先执行brpop命令的客户端可以获取弹出的值
client1 ->brpop list:test 0
...阻塞...
client2 ->brpop list:test 0
...阻塞...
client3 ->brpop list:test 0
...阻塞...

此时,另一个客户端执行了lpush list:test element

那么客户端1会取到元素,因为它最先执行brpop,客户端2和3继续阻塞等待。

内部编码

  • ziplist
  • linkedlist
  • quicklist(3.2版本以后默认)

使用场景

  1. 消息队列

lpush+brpop命令可以实现阻塞队列:lpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式抢列表尾部的元素

  1. 文章列表

每篇文章可以用哈希结构存储

hmset article:1 title xx timestamp 1276536196 content xxx

文章列表有序,且需要分页展示。可以将文章按顺序缓存到列表里,根据lrange key start end分页查询文章列表。

返回前10篇文章

lrange user:1:articles 0 9
for article in articles:
	hgetall (article)

如果文章数较多,hgetall会多次执行,可以考虑Pipeline批量获取。或者考虑序列化文章变为字符串类型,使用mget批量获取。

另外,如果文章列表较大,lrange在取中间范围的元素的性能会变差。内部编码用quicklist之后,性能会好。(but why?还需要更深入理解内部编码的实现)

?

Redis数据结构-list

上一篇:mathtype在word中的使用


下一篇:解Bug之路-ZooKeeper集群拒绝服务