设为首页 收藏本站
查看: 1011|回复: 0

[经验分享] Redis-3 数据类型详解之List

[复制链接]

尚未签到

发表于 2016-12-20 09:14:37 | 显示全部楼层 |阅读模式
1. 理论篇
  在学习List之前先对其来一点理论的了解是有好处的。
  简单来说比如 10,20,1,2,3  的序列就是一个List。不过 List 是继承自ArrayList 还是LinkedList,他们之间的差别还是很大的。LinkedList 意味着即使你的 List 列表中有一百万个数据,在 List 的头或者 尾部插入数据的时间都是恒定的。比如无论数组里面有10个或者1000万个元素,使用LPUSH 把一个元素插入到 List 的头部或者尾部的时候,他们的时间是相等的。
   
  那他的确定是什么呢?在使用下表访问 ArrayList 的元素的时候,它的速度很快,可以说是及时的;而在访问 LinkedList 的元素的额时候,速度就不那么快了,它与访问的元素的下标的数量是有关的。
   
  Redis List 是继承自LinkedList 的,因为对于数据库来说能够在长列表的时候非常快的插入数据是非常关键的。另一个重要的因素是你即将要看到的:Redis 可以在常数时间内取得常数长度。
   
  当访问一个大集合的中部元素是比较重要的时候,还有其他的数据结构可以使用--Sorted Set。我们后续的教程会讲 Sorted Set。
2. Redis List 入门
  LPUSH 命令添加一个新元素到一个列表的左边(头部),然而RPUSH 命令添加一个新元素到一个列表的右边(尾部)。最后,LRANGE命令在列表中获取一个范围的元素。
Java代码 


  • 127.0.0.1:6666> RPUSH mylist a  
  • (integer) 1  
  • 127.0.0.1:6666> rpush mylist b  
  • (integer) 2  
  • 127.0.0.1:6666> lpush mylist first  
  • (integer) 3  
  • 127.0.0.1:6666> lrange mylist 0 -1  
  • 1"first"  
  • 2"a"  
  • 3"b"  

  注意LRANGE 有两个下表,范围内的第一个和最后一个元素都会返回。两个下标都可以是负值,这告诉 Redis 从末尾开始计数:所以 -1 是最后一个元素,-2 是倒数第二个元素等等。
   
  正如你所见,RPUSH 添加元素到列表的右边,而LPUSH 添加元素到列表的左边。
  这两个命令都是可变参数的命令,这意味着你可以很随意的添加多个元素到列表中。
Java代码 


  • 127.0.0.1:6666> rpush mylist 1 2 3 4 5 "mylast"  
  • (integer) 9  
  • 127.0.0.1:6666> lrange mylist 0 -1  
  • 1"first"  
  • 2"a"  
  • 3"b"  
  • 4"1"  
  • 5"2"  
  • 6"3"  
  • 7"4"  
  • 8"5"  
  • 9"mylast"  

  Redis 列表上定义的一个重要的操作是弹出元素(pop elements)。弹出元素操作即使Redis 列表检索元素的操作,同时也是列表消除元素的操作。你可以从左边和右边弹出元素,与你从左边和右边添加元素是非常相似的:
Java代码 


  • 127.0.0.1:6666> rpush mylist a b c  
  • (integer) 3  
  • 127.0.0.1:6666> rpop mylist  
  • "c"  
  • 127.0.0.1:6666> lpop mylist  
  • "a"  
  • 127.0.0.1:6666> lpop mylist  
  • "b"  

  我们往列表中添加了三个元素,也弹出了三个元素,那么列表现在则是空的。如果我们尝试再继续弹出元素,那么将获得如下结果:
Java代码 


  • 127.0.0.1:6666> lpop mylist  
  • (nil)  

  如果列表中没有元素,Redis 则会返回一个 NULL 值。
 3. 列表的常见使用情形
  列表对于多任务是非常又有用的,下面是两个非常有代表性的用法:

  • 记录用户提交到社交网络上的最新的更新
  • 进程间的通信,使用生产者-消费者模式,生产者把一个条目压进列表中,消费者消费这些条目并且执行动作。Redis 有特别的列表命令可以使这种情况更加可靠和高效。
 
   注:此部分官方文档有实例,可以看看
 4.有上限的列表
在很多场景中,我们仅仅使用List存储最新的条目,无论他们是下面的:社交网络更新、日志或者其他什么。
 
Redis 列表允许我们使用列表作为一个有上限的集合,它使用LTRIM仅存储最新的条目并且丢弃最旧的数据。
LTRIM 命令与LRANGE命令十分相似,它不展示指定的元素范围而是把这个范围设置为新的列表值。给定的范围之外的元素会被移除。
Java代码 


  • 127.0.0.1:6666> rpush mylist 1 2 3 4 5  
  • (integer) 5  
  • 127.0.0.1:6666> ltrim mylist 0 2  
  • OK  
  • 127.0.0.1:6666> lrange mylist 0 -1  
  • 1"1"  
  • 2"2"  
  • 3"3"  

 
下面的 LTRIM 命令告诉Redis仅仅保留从下标0到2的元素,其他的都被丢弃。这就允许一个非常简单的但是有用的模式:对一个列表进行压入操作 +列表调整操作组合,这为了实现添加一个新的元素并且丢弃掉超出限制的元素:
Java代码 


  • LPUSH mylist <some element>  
  • LTRIM mylist 0 999  

 
 上面的组合添加一个新的元素,并且仅仅把最新的1000个元素保存入列表中。使用LRANGE你可以访问最顶部的元素而且不需要记住特定的老数据。
注:虽然LRANGE从技术上讲是个O(N) 命令,但是访问列表头部或者尾部的小范围是个及时的操作。
 
5. 列表的阻塞操作
 列表有一个特别的特性使其适合实现队列,并且通常作为一个内部进程通信系统的构建基块:阻塞操作。
 
比如你想要使用一个进程把条目压入列表,并且使用一个不同的进程来实际上对这些条目做一些工作。这是普通的生产者/消费者模式,并且可以使用下面的方式来实现:

  • 要把条目压入列表,生产者调用LPUSH
  • 要从列表中提取或者处理条目,消费者调用RPOP
然而,很有可能有时列表是空的并且没有什么可处理的,所以RPOP仅仅返回NULL。在这种情况下,消费者别强制等待一些时间并且使用RPOP重试。这被称作轮询(polling),并且在这种情形下他不是一个好的做法,因为它有如下缺点:

  • 强制Redis和客户端运行无用的命令(当列表为空的时候,所有的请求都在做无用功,他们仅仅返回NULL)
  • 在消费者NULL的时候,为条目的处理添加一个延迟,它等待一段时间。为了使延迟更小,we could wait less between calls to RPOP, with the effect of amplifying problem number 1, i.e. more useless calls to Redis.
所以,Redis实现了BRPOP 和 BLPOP 命令,他们是当列表为空时可以阻塞版本的 RPOP 和 LPOP :他们仅仅当一个新的元素被添加进入列表的时候或者当用户指定的过期时间到达的时候才返回给调用者。
 
下面是我们可以在工作者中(worker)调用BRPOP的例子:
 
Java代码 


  • 127.0.0.1:6666> brpop tasks 10  
  • 1"tasks"  
  • 2"12"  

   
 
这个效果是我在执行完上述的命令之后,程序阻塞了;然后在另一个客户端执行了 RPUSH tasks 12 命令,这时候阻塞的程序就会继续执行,因为它检测到了有新的元素的进入。
 
 brpop tasks 10 的含义是:等待 tasks 列表中的元素,但是如果在 5 秒以后还没有元素可以获取到的话就返回程序。
 
注意:你可以使用 0 作为过期时间以一直等待元素,并且你也可以指定多个而不止一个列表,这样可以同时等待多个列表,并且当第一个列表收到元素时收到通知。
 
关于BRPOP的几个值得注意的地方:
1. 客户端以一种有序的方式接受服务:当一个元素被其他客户端压入到列表中或者其他情况,一个列表阻塞等待的第一个客户端将会接收到服务。
2. 返回值与RPOP相比是不一样的:由于它也包含着键的名字,所以它是两个元素的数组,这是因为BRPOP 和 BLPOP 能够等待来自多个列表的元素。
3. 如果已经到了过期时间,那么将返回NULL。
 
关于列表和他的阻塞选项,你还有很多需要了解的。关于下述的内容建议你读更多资料:

  • 可以使用RPOPLPUSH来构建安全的队列或者循环队列
  • BRPOPLPUSH 是命令的命令的阻塞备选方案
额。。。下面依然是我建的一个公众帐号,可以关注一下哦,谢谢
 
DSC0000.jpg

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-316778-1-1.html 上篇帖子: redis对关系数据库的优势 下篇帖子: redis存储类型以及持久化存储方式介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表