redis list 使用
参考:http://redis.cn/commands.html#list
- BLPOP key [key ...] timeout删除,并获得该列表中的第一元素,或阻塞,直到有一个可用
- BRPOP key [key ...] timeout删除,并获得该列表中的最后一个元素,或阻塞,直到有一个可用
- BRPOPLPUSH source destination timeout弹出一个列表的值,将它推到另一个列表,并返回它;或阻塞,直到有一个可用
- LINDEX key index获取一个元素,通过其索引列表
- LINSERT key BEFORE|AFTER pivot value在列表中的另一个元素之前或之后插入一个元素
- LLEN key获得队列(List)的长度
- LPOP key从队列的左边出队一个元素
- LPUSH key value [value ...]从队列的左边入队一个或多个元素
- LPUSHX key value当队列存在时,从队到左边入队一个元素
- LRANGE key start stop从列表中获取指定返回的元素
- LREM key count value从列表中删除元素
- LSET key index value设置队列里面一个元素的值
- LTRIM key start stop修剪到指定范围内的清单
- RPOP key从队列的右边出队一个元素
- RPOPLPUSH source destination删除列表中的最后一个元素,将其追加到另一个列表
- RPUSH key value [value ...]从队列的右边入队一个元素
- RPUSHX key value从队
lpush:
将所有指定的值插入到存于 key
的列表的头部。如果 key
不存在,那么在进行 push 操作前会创建一个空列表。 如果 key
对应的值不是一个 list 的话,那么会返回一个错误。
可以使用一个命令把多个元素 push 进入列表,只需在命令末尾加上多个指定的参数。元素是从最左端的到最右端的、一个接一个被插入到 list 的头部。 所以对于这个命令例子 LPUSH mylist a b c
,返回的列表是 c
为第一个元素, b
为第二个元素, a
为第三个元素。
返回值
整型回复: 在 push 操作后的 list 长度。
历史
>= 2.4
: 接受多个value
参数。版本老于 2.4 的 Redis 只能每条命令 push 一个值。
例子
- (integer) 1
redis> LPUSH mylist "hello"
- (integer) 2
redis> LRANGE mylist 0 -1
- 1) "hello"
- 2) "world" (说明list是从头部插入的)
redis>
lpushx:
只有当 key
已经存在并且存着一个 list 的时候,在这个 key
下面的 list 的头部插入 value
。 与 LPUSH 相反,当 key
不存在的时候不会进行任何操作。
返回值
整型回复: 在 push 操作后的 list 长度。
LRANGE key start stop
返回存储在 key
的列表里指定范围内的元素。 start
和 end
偏移量都是基于0的下标,即list的第一个元素下标是0
(list的表头),第二个元素下标是1
,以此类推。
偏移量也可以是负数,表示偏移量是从list尾部开始计数。 例如, -1
表示列表的最后一个元素,-2
是倒数第二个,以此类推。
在不同编程语言里,关于求范围函数的一致性
需要注意的是,如果你有一个list,里面的元素是从0到100,那么 LRANGE list 0 10
这个命令会返回11个元素,即最右边的那个元素也会被包含在内。 在你所使用的编程语言里,这一点可能是也可能不是跟那些求范围有关的函数都是一致的。(像Ruby的 Range.new
,Array#slice
或者Python的 range()
函数。)
超过范围的下标
当下标超过list范围的时候不会产生error。 如果start
比list的尾部下标大的时候,会返回一个空列表。 如果stop
比list的实际尾部大的时候,Redis会当它是最后一个元素的下标。
返回值
多批量回复: 指定范围里的列表元素。
lpop:
移除并且返回 key
对应的 list 的第一个元素。
返回值
批量回复: 返回第一个元素的值,或者当 key
不存在时返回 nil
。
例子
- (integer) 1
- LLEn key
加入版本 1.0.0。
时间复杂度: O(1)。
返回存储在 key
里的list的长度。 如果 key
不存在,那么就被看作是空list,并且返回长度为 0
。 当存储在 key
里的值不是一个list的话,会返回error。
LREM/LSET/LINDEX/LTRIM:
LREM key count value
- 加入版本 1.0.。
- 时间复杂度: O(N),此处N表示list的长度。
- 从存于 key 的列表里移除前 count 次出现的值为 value 的元素。 这个 count 参数通过下面几种方式影响这个操作:
- count > : 从头往尾移除值为 value 的元素。
- count < : 从尾往头移除值为 value 的元素。
- count = : 移除所有值为 value 的元素。
- 比如, LREM list - "hello" 会从存于 list 的列表里移除最后两个出现的 "hello"。
- 需要注意的是,如果list里没有存在key就会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 。
- 返回值
- 整型回复: 被移除的元素个数。
- 例子
- redis> RPUSH mylist "hello"
- (integer)
- redis> RPUSH mylist "hello"
- (integer)
- redis> RPUSH mylist "foo"
- (integer)
- redis> RPUSH mylist "hello"
- (integer)
- redis> LREM mylist - "hello"
- (integer)
- redis> LRANGE mylist -
- ) "hello"
- ) "foo"
- redis>
lindex key index:
- 加入版本 1.0.。
- 时间复杂度: O(N),此处N是通过下标遍历到要找的元素所经过元素个数。也就是说要询问list里的第一个或者最后一个元素的复杂度是O()。
- 返回列表里的元素的索引 index 存储在 key 里面。 下标是从0开始索引的,所以 是表示第一个元素, 表示第二个元素,并以此类推。 负数索引用于指定从列表尾部开始索引的元素。在这种方法下,- 表示最后一个元素,- 表示倒数第二个元素,并以此往前推。
- 当 key 位置的值不是一个列表的时候,会返回一个error。
- 返回值
- 批量回复:请求的对应元素,或者当 index 超过范围的时候返回 nil。
redis> LPUSH mylist "World"
- (integer) 1
redis> LPUSH mylist "Hello"
- (integer) 2
redis> LINDEX mylist 0
- "Hello"
redis> LINDEX mylist -1
- "World"
redis> LINDEX mylist 3
- (nil)
redis>
lset key index value:
- 加入版本 1.0.。
- 时间复杂度: O(N),此处N表示list的长度。设置list里第一个或者最后一个元素的复杂度是O()。
- 设置 index 位置的list元素的值为 value。 更多关于 index 参数的信息,详见 LINDEX。
- 当index超出范围时会返回一个error。
- 返回值
- 状态回复
- 例子
- redis> RPUSH mylist "one"
- (integer)
- redis> RPUSH mylist "two"
- (integer)
- redis> RPUSH mylist "three"
- (integer)
- redis> LSET mylist "four"
- OK
- redis> LSET mylist - "five"
- OK
- redis> LRANGE mylist -
- ) "four"
- ) "five"
- ) "three"
- redis>
LTRIM key start stop
- 加入版本 1.0.。
- 时间复杂度: O(N) 这里的N是该操作中要被移除掉的元素个数。
- 修剪(trim)一个已存在的 list,这样 list 就会只包含指定范围的指定元素。start 和 stop 都是由0开始计数的, 这里的 0 是列表里的第一个元素(表头),1 是第二个元素,以此类推。
- 例如: LTRIM foobar 将会对存储在 foobar 的列表进行修剪,只保留列表里的前3个元素。
- start 和 end 也可以用负数来表示与表尾的偏移量,比如 - 表示列表里的最后一个元素, - 表示倒数第二个,等等。
- 超过范围的下标并不会产生错误:如果 start 超过列表尾部,或者 start > end,结果会是列表变成空表(即该 key 会被移除)。 如果 end 超过列表尾部,Redis 会将其当作列表的最后一个元素。
- LTRIM 的一个常见用法是和 LPUSH / RPUSH 一起使用。 例如:
- LPUSH mylist someelement
- LTRIM mylist 0 99
- 这一对命令会将一个新的元素 push 进列表里,并保证该列表不会增长到超过100个元素。这个是很有用的,比如当用 Redis 来存储日志。 需要特别注意的是,当用这种方式来使用 LTRIM 的时候,操作的复杂度是 O() , 因为平均情况下,每次只有一个元素会被移除。
- 返回值
- 状态回复
- 例子
- redis> RPUSH mylist "one"
- (integer)
- redis> RPUSH mylist "two"
- (integer)
- redis> RPUSH mylist "three"
- (integer)
- redis> LTRIM mylist -
- OK
- redis> LRANGE mylist -
- ) "two"
- ) "three"
- redis>
LINSERT key BEFORE|AFTER pivot value
- 加入版本 2.2.。
- 时间复杂度: O(N),此处N是在看见 pivot 值之前遍历过的元素个数。 这意味着在list最左端(表头)进行插入的复杂度是O(),而在list最右端(表尾)进行插入是O(N)。
- 把 value 插入存于 key 的列表中在基准值 pivot 的前面或后面。
- 当 key 不存在时,这个list会被看作是空list,任何操作都不会发生。
- 当 key 存在,但保存的不是一个list的时候,会返回error。
- 返回值
- 整型回复: 经过插入操作后的list长度,或者当 pivot 值找不到的时候返回 -。
- 例子
- redis> RPUSH mylist "Hello"
- (integer)
- redis> RPUSH mylist "World"
- (integer)
- redis> LINSERT mylist BEFORE "World" "There"
- (integer)
- redis> LRANGE mylist -
- ) "Hello"
- ) "There"
- ) "World"
- redis>
RPUSH/RPUSHX/RPOP/RPOPLPUSH:
- #删除该键,以便于后面的测试。
- redis 127.0.0.1:> del mykey
- (integer)
- #从链表的尾部插入参数中给出的values,插入顺序是从左到右依次插入。
- redis 127.0.0.1:> rpush mykey a b c d
- (integer)
- #通过lrange的可以获悉rpush在插入多值时的插入顺序。
- redis 127.0.0.1:> lrange mykey -
- ) "a"
- ) "b"
- ) "c"
- ) "d"
- #该键已经存在并且包含4个元素,rpushx命令将执行成功,并将元素e插入到链表的尾部。
- redis 127.0.0.1:> rpushx mykey e
- (integer)
- #通过lindex命令可以看出之前的rpushx命令确实执行成功,因为索引值为4的元素已经是新元素了。
- redis 127.0.0.1:> lindex mykey
- "e"
- #由于mykey2键并不存在,因此该命令不会插入数据,其返回值为0。
- redis 127.0.0.1:> rpushx mykey2 e
- (integer)
- #在执行rpoplpush命令前,先看一下mykey中链表的元素有哪些,注意他们的位置关系。
- redis 127.0.0.1:> lrange mykey -
- ) "a"
- ) "b"
- ) "c"
- ) "d"
- ) "e"
- #将mykey的尾部元素e弹出,同时再插入到mykey2的头部(原子性的完成这两步操作)。
- redis 127.0.0.1:> rpoplpush mykey mykey2
- "e"
- #通过lrange命令查看mykey在弹出尾部元素后的结果。
- redis 127.0.0.1:> lrange mykey -
- ) "a"
- ) "b"
- ) "c"
- ) "d"
- #通过lrange命令查看mykey2在插入元素后的结果。
- redis 127.0.0.1:> lrange mykey2 -
- ) "e"
- #将source和destination设为同一键,将mykey中的尾部元素移到其头部。
- redis 127.0.0.1:> rpoplpush mykey mykey
- "d"
- #查看移动结果。
- redis 127.0.0.1:> lrange mykey -
- ) "d"
- ) "a"
- ) "b"
- ) "c"
RPOPLPUSH source destination
- 加入版本 1.2.。
- 时间复杂度: O()。
- 原子性地返回并移除存储在 source 的列表的最后一个元素(列表尾部元素), 并把该元素放入存储在 destination 的列表的第一个元素位置(列表头部)。
- 例如:假设 source 存储着列表 a,b,c, destination存储着列表 x,y,z。 执行 RPOPLPUSH 得到的结果是 source 保存着列表 a,b ,而 destination 保存着列表 c,x,y,z。
- 如果 source 不存在,那么会返回 nil 值,并且不会执行任何操作。 如果 source 和 destination 是同样的,那么这个操作等同于移除列表最后一个元素并且把该元素放在列表头部, 所以这个命令也可以当作是一个旋转列表的命令。
- 返回值
- 批量回复: 被移除和放入的元素
- 例子
- redis> RPUSH mylist "one"
- (integer)
- redis> RPUSH mylist "two"
- (integer)
- redis> RPUSH mylist "three"
- (integer)
- redis> RPOPLPUSH mylist myotherlist
- "three"
- redis> LRANGE mylist -
- ) "one"
- ) "two"
- redis> LRANGE myotherlist -
- ) "three"
- redis>
模式:安全的队列
Redis通常都被用做一个处理各种后台工作或消息任务的消息服务器。 一个简单的队列模式就是:生产者把消息放入一个列表中,等待消息的消费者用 RPOP 命令(用轮询方式), 或者用 BRPOP 命令(如果客户端使用阻塞操作会更好)来得到这个消息。
然而,因为消息有可能会丢失,所以这种队列并是不安全的。例如,当接收到消息后,出现了网络问题或者消费者端崩溃了, 那么这个消息就丢失了。
RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH) 提供了一种方法来避免这个问题:消费者端取到消息的同时把该消息放入一个正在处理中的列表。 当消息被处理了之后,该命令会使用 LREM 命令来移除正在处理中列表中的对应消息。
另外,可以添加一个客户端来监控这个正在处理中列表,如果有某些消息已经在这个列表中存在很长时间了(即超过一定的处理时限), 那么这个客户端会把这些超时消息重新加入到队列中。
模式:循环列表
RPOPLPUSH 命令的 source
和 destination
是相同的话, 那么客户端在访问一个拥有n个元素的列表时,可以在 O(N) 时间里一个接一个获取列表元素, 而不用像 LRANGE 那样需要把整个列表从服务器端传送到客户端。
上面这种模式即使在以下两种情况下照样能很好地工作: * 有多个客户端同时对同一个列表进行旋转(rotating):它们会取得不同的元素,直到列表里所有元素都被访问过,又从头开始这个操作。 * 有其他客户端在往列表末端加入新的元素。
这个模式让我们可以很容易地实现这样一个系统:有 N 个客户端,需要连续不断地对一批元素进行处理,而且处理的过程必须尽可能地快。 一个典型的例子就是服务器上的监控程序:它们需要在尽可能短的时间内,并行地检查一批网站,确保它们的可访问性。
值得注意的是,使用这个模式的客户端是易于扩展(scalable)且安全的(reliable),因为即使客户端把接收到的消息丢失了, 这个消息依然存在于队列中,等下次迭代到它的时候,由其他客户端进行处理。
链表结构的小技巧:
针对链表结构的Value,Redis在其官方文档中给出了一些实用技巧,如RPOPLPUSH命令,下面给出具体的解释。
Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。
参考:http://www.cnblogs.com/stephen-liu74/archive/2012/03/16/2351859.html
redis list 使用的更多相关文章
- 使用redis构建可靠分布式锁
关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...
- Ignite性能测试以及对redis的对比
测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...
- mac osx 安装redis扩展
1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...
- Redis/HBase/Tair比较
KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式 支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...
- Redis数据库
Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...
- redis 学习笔记(2)
redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...
- redis 学习笔记(1)
redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...
- python+uwsgi导致redis无法长链接引起性能下降问题记录
今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...
- nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...
- windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...
随机推荐
- liunx上运行mybase
mybase 是个人知识管理软件,国内用他的人很多,尤其是程序员.我也是mybase的忠实使用者,有大量的积累. 以前一直用Windows,mybase使用完全没有问题,后来转投ubuntu阵营 ...
- Mac终端编译运行C++
1.在编辑器中写好C++代码 2.打开终端打开文件对应的地址 3.用g++命令来编译.cpp文件 4.用./文件名来运行 观察文件的目录可发现 g++ 源文件名 编译源文件,产生a.out ./文件名 ...
- 【转】Android Studio -修改LogCat的颜色*美爆了*
原文网址:http://www.2cto.com/kf/201505/400357.html 一. 先看效果 二.设置 File->Settings 或Ctrl + Alt +S 找到 Edit ...
- tencent://message协议
tencent://message协议 |举报|字号 订阅 相信很多朋友在访问别人的博客.网上商城时可能会发现上都有这样的小玩意, 点击下就可以弹出对话框和主人进行对话,而且无需加对方为好友. ...
- poj 1026(置换群)
题意:给你一个变换规则,和一个字符串,问经过k次变换后得到的字符串. 思路:开始的时候试图去找它的整个周期,谁知道周期太大了,各种RE,后来在得知此题需要用置换群来优化,第一次接触置换群学习了下! 代 ...
- 使ViewFlipper中的WebView实现手势效果
使ViewFlipper中的WebView实现手势效果 今天写Blog阅读器的时候遇到了这个问题,把它分享给大家,让同样是新手们少走冤枉路始初写这个功能的时候,用过了好多方法,也耗了不少时间去研究 ...
- java移动/赋值文件 copy/move file
public class FileAccess { public static boolean Move(File srcFile, String destPath) { // Destination ...
- bjfu1238 卡特兰数取余
题目就是指定n,求卡特兰数Ca(n)%m.求卡特兰数有递推公式.通项公式和近似公式三种,因为要取余,所以近似公式直接无法使用,递推公式我简单试了一下,TLE.所以只能从通项公式入手. Ca(n) = ...
- java ant 命令大全
ANT命令总结 1 Ant是什么? Apache Ant 是一个基于 Java的生成工具.生成工具在软件开发中用来将源代码和其他输入文件转换为可执行文件的形式(也有可能转换为可安装的产品映像形式).随 ...
- [原创]cocos2d-x + Lua接入iOS原生SDK的实现方案
相信很多朋友在使用cocos2d-x+lua开发游戏时都遇到过接入iOS原生SDK的问题,比如常见的接应用内支付SDK,广告SDK或是一些社交平台SDK等等,我也没少接过这类SDK.这篇文章主要是对我 ...