Redis 学习笔记(三)五大基本数据类型List

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 都可以进行插入。

在两侧插入列表效率高,在中间元素上进行操作效率低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值