redis的基本数据类型为:
- string
- list
- set
- hash
- zset
List数据类型(列表)
在redis中,可以将列表当成栈(先进后出)、队列(先进先出)和阻塞队列(一个线程往列表中放消息,另一个线程从列表中取消息。当队列为空:取消息线程被阻塞;当队列中满了:放消息线程被阻塞)。
所有的list命令都以"L"为开头:
lpush <list> <value> #将value插入到list列表头部(从左侧添加);当list不存在时先创建列表
rpush <list> <value> #将value插入到list列表尾部(从右侧添加);当list不存在时先创建列表
lpushx <list> <value> #将value插入到list列表头部(从左侧添加);当list不存在时不进行操作
rpushx <list> <value> #将value插入到list列表尾部(从右侧添加);当list不存在时不进行操作
lpop <list> #移除list左侧第一个元素并返回这个元素值;当list不存在时返回值为nil
rpop <list> #移除list右侧第一个元素并返回这个元素值;当list不存在时返回值为nil
rpoplpush <list> <listN> #返回并移除list尾部第一个元素,并将此元素插入到listN的头部(原子性)
#当list不存在时不进行操作;当list和listN相同时,就是将尾部元素放到头部
rpoplpush 命令扩展
一、安全的队列模式
Redis通常都被用做一个处理各种后台工作或消息任务的消息服务器。 一个简单的队列模式就是:生产者把消息放入一个列表中,等待消息的消费者用
RPOP 命令(用轮询方式), 或者用 BRPOP 命令(如果客户端使用阻塞操作会更好)来得到这个消息。然而,因为消息有可能会丢失,所以这种队列并是不安全的。例如,当接收到消息后,出现了网络问题或者消费者端崩溃了, 那么这个消息就丢失了。
RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH)
提供了一种方法来避免这个问题:消费者端取到消息的同时把该消息放入一个正在处理中的列表。 当消息被处理了之后,该命令会使用 LREM
命令来移除正在处理中列表中的对应消息。另外,可以添加一个客户端来监控这个正在处理中列表,如果有某些消息已经在这个列表中存在很长时间了(即超过一定的处理时限),
那么这个客户端会把这些超时消息重新加入到队列中。二、循环列表的模式
RPOPLPUSH 命令的 source 和 destination 是相同的话, 那么客户端在访问一个拥有n个元素的列表时,可以在
O(N) 时间里一个接一个获取列表元素, 而不用像 LRANGE 那样需要把整个列表从服务器端传送到客户端。上面这种模式即使在以下两种情况下照样能很好地工作: *
有多个客户端同时对同一个列表进行旋转(rotating):它们会取得不同的元素,直到列表里所有元素都被访问过,又从头开始这个操作。 *
有其他客户端在往列表末端加入新的元素。这个模式让我们可以很容易地实现这样一个系统:有 N 个客户端,需要连续不断地对一批元素进行处理,而且处理的过程必须尽可能地快。
一个典型的例子就是服务器上的监控程序:它们需要在尽可能短的时间内,并行地检查一批网站,确保它们的可访问性。值得注意的是,使用这个模式的客户端是易于扩展(scalable)且安全的(reliable),因为即使客户端把接收到的消息丢失了,
这个消息依然存在于队列中,等下次迭代到它的时候,由其他客户端进行处理。
链接: 引用redis官网
lset <list> <n> <valueN> #将list中指定下标n的元素替换成valueN;当n超出范围则返回error
lrem <list> <n> <value> #移除list中值为value的元素,返回值为移除的元素个数;当list不存在返回0
#n>0:从头到尾依次移除n个value;
#n<0:从尾到头依次移除n个value;
#n=0:移除所有的value;
linsert <list> <before/after> <value> <valueN> #将valueN插到值为value的元素前面/后面;
#当list不存在时则不进行操作
lrange <list> <start> <end> #获取list从start到end的闭区间元素
#若start为0,end为-1则表示获取全部元素
lindex <list> <n> #获取list中索引下标为n的元素值;当n超过范围时返回值为nil
#n>=0:获取从头到尾的第n+1个value;
#n<0:获取从尾到头的第n个value;
llen <list> #获取list中的元素个数
ltrim <list> <start> <end> #截取出list从start到end的闭区间元素(改变了list)
阻塞队列
1、blpop
blpop <list1> <list2>... <timeout>
当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP 命令阻塞。当给定多个key参数时,按参数key的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。
当 BLPOP 命令引起客户端阻塞并且设置了一个非零的超时参数 timeout 的时候, 若经过了指定的 timeout 仍没有出现一个针对某一特定 key 的 push 操作,则客户端会解除阻塞状态并且返回一个 nil 的多组合值(multi-bulk value)。
timeout 参数表示的是一个指定阻塞的最大秒数的整型值。当 timeout 为 0 是表示阻塞时间无限制。
扩展:
当多个元素被 push 进入一个 list 时 BLPOP 的行为 :
对于 Redis 2.6 来说,所采取的行为是先执行多个 push 命令,然后在执行了这个命令之后再去服务被阻塞的客户端。看看下面命令顺序。
Client A: BLPOP foo 0
Client B: LPUSH foo a b c
如果上面的情况是发生在 Redis 2.6 或更高版本的服务器上,客户端 A 会接收到 c 元素,因为在 LPUSH 命令执行后,list 包含了 c,b,a 这三个元素,所以从左边取一个元素就会返回 c。
相反,Redis 2.4 是以不同的方式工作的:客户端会在 push 操作的上下文中被服务,所以当 LPUSH foo a b c 开始往 list 中 push 第一个元素,它就被传送给客户端A,也就是客户端A会接收到 a(第一个被 push 的元素)。
2、brpop
brpop <list1> <list2>... <timeout>
与blpop命令相反,弹出尾部的第一个元素。
3、brpoplpush
brpoplpush <list> <listN> <timeout>
当 list包含元素的时候,这个命令表现得跟 rpoplpush 一模一样。 当 list是空的时候,Redis将会阻塞这个连接,直到另一个客户端 push 元素进入或者达到 timeout 时限。 timeout 为 0 能用于无限期阻塞客户端。
小结
list是一个链表,lpush、rpush、linsert before/after 都可以进行插入。
在两侧插入列表效率高,在中间元素上进行操作效率低。