美文网首页
Redis数据类型 - Lists

Redis数据类型 - Lists

作者: 马蹄哒 | 来源:发表于2018-09-16 14:34 被阅读0次

一般来说,列表是有序元素的序列:10、20、1、2、3是一个列表。基于数组实现的列表和基于链表( Linked Lists)实现的列表的属性是不同的。

Redis列表是通过链表实现的。这意味着,即使在列表中有数百万个元素,在列表的头部或尾部添加新元素的操作所耗费的时间是恒定的。使用LPUSH命令向包含10个元素的列表头部添加新元素的速度与向包含1000万个元素的列表头部添加一个元素的速度是一样的。

缺点是,通过索引访问一个基于数组实现的Lists中的元素速度是非常快的(恒定的访问时间),而相比之下,在基于链表实现的Lists中速度就没有那么快(在这种情况下,操作需要的时间与被访问元素的索引成正比)。

Redis列表采用链表来实现的主要原因是,对于数据库系统来说,能够以非常快的速度向一个非常长的列表添加元素是非常重要的。另一个强大的优势,就是Redis列表可以在恒定的时间内获取恒定长度的元素。

常用命令:
lpush listname value 向列表的左边(头部)添加一个元素;也可同时添加多个值,用空格隔开
rpush listname value 向列表的右边(尾部)添加一个元素;也可同时添加多个值,用空格隔开
lrange listname 0 -1 获取列表的所有元素
lpop listname 取出列表头部的第一个元素(列表中的元素会减少),如果没有则返回:nil;
rpop listname 取出列表尾部的最后一个元素(列表中的元素会减少),如果没有则返回:nil;

使用场景:
Lists非常有用,下面是两个例子:
1.存储用户在社交网络上发布的最新动态。
2.进程之间的通信。使用消费者-生产者模式,其中生产者将项目推入列表,消费者(通常是worker进程)使用这些项目并执行操作。Redis有特殊的列表命令来使这些操作更加可靠和高效。

例如,流行的Ruby库resque和sidekiq都在底层使用Redis列表来实现。
假设想你在主页显示社交网络中发布的最新照片,希望加快访问速度,可以这样做:
a. 每当用户发布新照片时,我们都会用LPUSH将其ID添加到列表中。
b. 当用户访问主页时,我们使用lrange 0 9来获取最新发布的10个条目。

限定列表(Capped lists)
有时候我们只想使用列表来存储最新的数据,比如,社交网络更新、日志或任何其他东西。
Redis允许我们使用列表作为限定集合,只保持最新的N条记录,使用LTRIM命令丢弃所有旧的的记录。
LTRIM命令与LRANGE类似,但是它不是显示指定范围内的元素,而是将指定范围内的元素设置为列表的值。所有超出给定范围的元素都被删除。
一个非常简单但有用的模式:一起执行列表lpush操作+列表ltrim操作,以便添加一个新元素并丢弃超过限制的元素:

LPUSH mylist <some element>
LTRIM mylist 0 999

阻塞操作
列表的特性使它适合用来实现队列,并且通常作为进程间通信系统的构建块:阻塞操作。

假设你想用一个进程将元素推入列表,并使用不同的进程来实际处理这元素。这就是常见的生产者/消费者模式,可以通过以下简单的方式实现:
1. 将元素推入列表中,生产者会调用LPUSH。
2. 要从列表中提取/处理元素,消费者调用RPOP。

然而,有时候列表是空的,没有什么要处理的,所以RPOP只返回NULL。在这种情况下,消费者必须等待一段时间,然后再用RPOP重试一次。这被称为轮询(polling),在这种情况下使用RPOP并不是一个好主意,因为它有几个缺点:
1. 强制Redis和客户端处理无用的命令(当列表为空时,所有的请求都没有作用,它们只会返回NULL)。
2. 元素的处理会产生延迟,因为在worker接收到NULL之后,它会等待一段时间。即使减小延迟,可以在调用RPOP之间等待更少的时间,但这样会加重问题1,也就是增加对Redis无用的调用。

因此,Redis实现了名为BRPOP和BLPOP的命令,这些命令是RPOP和LPOP的一个版本,当列表为空时,它们会阻塞:只有当列表中添加新元素或达到用户指定的超时时间,它们才会返回给调用者。

brpop tasks 5  #等待列表tasks中的元素,但如果5秒后没有可用元素,则返回

你可以使用0作为超时时间来永远等待列表的元素,并且还可以同时指定多个列表而不仅仅是一个列表,以便同时等待多个列表的,并在第一个列表有可用元素时获得通知。
关于BRPOP有几点需要注意:
1. 客户端以一种有序的方式获得响应:当其他客户端向列表推入一个元素时,阻塞等待这个列表的第一个客户端,优先得到服务。
2. BRPOP返回值与RPOP不同:它返回包含两个元素的数组,(除了值)它还包含键的名称,因为BRPOP和BLPOP能够阻塞等待多个列表中的元素。
3. 如果超时,则返回NULL。

  • 可以使用RPOPLPUSH构建更安全的队列或回转队列。
  • 还有一个命令的阻塞变体:BRPOPLPUSH
自动创建和删除键

到目前为止,在我们的示例中,我们从未在推送元素之前创建过空列表,或者当列表内没有元素时删除空列表。Redis的职责是在列表为空时删除键,或者当键不存在,我们试图向其添加元素时,创建一个空列表,例如,LPUSH。

这不是列表特有的,它适用于由多个元素组成的所有Redis数据类型——Sets、Sorted Sets和Hashes。

基本上我们可以用三个规则来概括这个行为:

  1. 当我们向聚合数据类型(aggregate data type)添加元素时,如果目标键不存在,则在添加元素之前创建一个空的聚合数据类型。
  2. 当我们从聚合数据类型中删除元素时,如果值为空,则键将自动销毁。
  3. 对空键调用诸如LLEN(返回列表的长度)之类的只读命令或使用写命令删除元素,总是会产生相同的结果,就好像该键持有命令希望找到的类型的空聚合类型一样。

规则1的例子:

127.0.0.1:6379> exists mylist
(integer) 0
127.0.0.1:6379> lpush mylist 1 2 3
(integer) 3
127.0.0.1:6379> exists mylist
(integer) 1

但如果键已经存在,我们不能对错误的类型进行操作:

127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> lpush foo 1 2 3
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> type foo
string

规则2的例子:
移除所有元素之后,键也不存在了。

127.0.0.1:6379> lpush mylist 1 2 3
(integer) 3
127.0.0.1:6379> exists mylist
(integer) 1
127.0.0.1:6379> lpop mylist
"3"
127.0.0.1:6379> lpop mylist
"2"
127.0.0.1:6379> lpop mylist
"1"
127.0.0.1:6379> exists mylist
(integer) 0

规则3的例子:

127.0.0.1:6379> exists mylist
(integer) 0
127.0.0.1:6379> llen mylist
(integer) 0
127.0.0.1:6379> lpop mylist
(nil)

相关文章

  • Redis的安装和部署

    Redis的安装和部署 基本知识 Redis的数据类型:字符串、列表(lists)、集合(sets)、有序集合(s...

  • 用了这么久redis,你了解几种redis数据类型

    简单介绍一下redis的几种数据类型: Strings,Lists,Sets, Hashe,Sorted sets...

  • Redis数据类型 - Lists

    一般来说,列表是有序元素的序列:10、20、1、2、3是一个列表。基于数组实现的列表和基于链表( Linked L...

  • Redis从入门到精通(二、Redis的数据类型)

    此篇罗列了 Redis 的所有数据类型并介绍了常用的5种数据类型(strings,Lists,Hashes,Set...

  • Redis安装和部署

    基本知识 1、Redis的数据类型: 字符串、列表(lists)、集合(sets)、有序集合(sorts sets...

  • Redis:安装和部署、Redis命令详解

    一、基本知识 1、Redis的数据类型: 字符串、列表(lists)、集合(sets)、有序集合(sorts se...

  • Redis' lists

    Redis列表基本操作命令 Redis list底层结构 Redis list由链表来实现。在Redis中链表的应...

  • Redis数据结构 之 Lists

    本文的示例代码参考redis-lists.py Python Python环境搭建详细参考pyenv Redis ...

  • Go-Redis

    Redis支持的数据结构 Redis支持诸如字符串(strings)、哈希(hashes)、列表(lists)、集...

  • Redis命令:Lists

    Lists是一组有序、可重复的元素集合。 LPUSH/RPUSH分别在队首(左侧)和队尾(右侧)插入指定元素。如果...

网友评论

      本文标题:Redis数据类型 - Lists

      本文链接:https://www.haomeiwen.com/subject/zywdgftx.html