铜陵app网站做营销招聘,投资网站模板,为什么大家用wordpress建网站,十大品牌营销策划公司目录 List类型介绍特点 List数据结构附#xff1a;3.2以前的版本(介绍一下压缩列表和双向链表)压缩列表ZipList双向链表LinkedList 常用命令lpush示例 lpushx示例 rpush示例 rpushx示例 LPOP示例 RPOP示例 BLPOP非阻塞行为阻塞行为相同的 key 被多个客户端同时阻塞在 MULTI/EX… 目录 List类型介绍特点 List数据结构附3.2以前的版本(介绍一下压缩列表和双向链表)压缩列表ZipList双向链表LinkedList 常用命令lpush示例 lpushx示例 rpush示例 rpushx示例 LPOP示例 RPOP示例 BLPOP非阻塞行为阻塞行为相同的 key 被多个客户端同时阻塞在 MULTI/EXEC 事务中的 BLPOP BRPOP示例 LLEN示例 LRANGE注意 LRANGE 命令和编程语言区间函数的区别超出范围的下标示例 LREM示例 LSET示例 LTRIM注意 LTRIM 命令和编程语言区间函数的区别超出范围的下标示例 LINDEX示例 LINSERT示例 RPOPLPUSH示例应用1安全的队列应用2循环列表 BRPOPLPUSH示例应用1安全队列应用2循环列表 List类型介绍
单键多值Redis 列表是简单的字符串列表按照插⼊顺序排序。你可以添加⼀个元素到列表的头部左边或者尾部右边。它的底层实际是个双向链表对两端的操作性能很⾼通过索引下标的操作中间的节点性能会较差。Redis 中列表List类型是用来存储多个有序的字符串列表中的每个字符串成为元素Eelement一个列表最多可以存储 2^32-1 个元素。在 Redis 中可以对列表两端插入push和弹出pop还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构可以充当栈和队列的角色在实际开发中有很多应用场景。
特点
列表中的元素是有序的即可以通过索引下标获取某个元素或者某个范围内的元素列表列表中的元素可以是重复的
List数据结构 Redis3.2 版本开始List 类型数据使用的底层数据结构是快速链表快速列表是以压缩列表为节点的双向链表将双向链表按段切分每一段使用压缩列表进行内存的连续存储多个压缩列表通过 prev 和 next 指针组成的双向链。 ⾸先在列表元素较少的情况下会使⽤⼀块连续的内存存储这个结构是 ziplist也即是压缩列表。它将所有的元素紧挨着⼀起存储分配的是⼀块连续的内存。 当数据量⽐较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太⼤会⽐较浪费空间。⽐如这个列表⾥存的只是 int 类型的数据结构上还需要两个额外的指针 prev 和 next。 Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使⽤双向指针串起来使⽤。这样既满⾜了快速的插⼊删除性能⼜不会出现太⼤的空间冗余。 考虑到链表的以上缺点Redis 后续版本对列表数据结构进行改造使用 QucikList 代替了 ZipList 和 LinkedList。 作为 ZipList 和 LinkedList 的混合体它将 LinkedList 按段切分每一段使用 ZipList 来紧凑存储多个 ZipList 之间使用双向指针串接起来。
附3.2以前的版本(介绍一下压缩列表和双向链表)
压缩列表ZipList
压缩列表是一块连续的内存空间 (像内存连续的数组但每个元素长度不同)一个 ziplist 可以包含多个节点entry。元素之间紧挨着存储没有任何冗余空隙。 压缩列表的本质就是一个数组只不过是增加了 “列表长度”、“尾部偏移量”、“列表元素个数” 以及 “列表结束标识”这样的话就有利于快速的寻找列表的首、尾节点.压缩列表将表中每一项存放在前后连续的地址空间内每一项因占用的空间不同而采用变长编码。由于内存是连续分配的所以遍历速度很快。当我们的 List 列表数据量比较少的时候且存储的数据轻量的如小整数值、短字符串时候 Redis 就会通过压缩列表来进行底层实现。
双向链表LinkedList LinkedList 是标准的双向链表Node 节点包含 prev 和 next 指针分别指向后继与前驱节点因此从双向链表中的任意一个节点开始都可以很方便地访问其前驱与后继节点。 LinkedList 可以进行双向遍历添加删除元素快 O(1)查找元素慢 O(n)高效实现了 LPUSH 、RPOP、RPOPLPUSH但由于需要为每个节点分配额外的内存空间所以会浪费一定的内存空间。这种编码方式适用于元素数量较多或者元素较大的场景。 LinkedList 结构为链表提供了表头指针 head、表尾指针 tail以及节点数量计算 len。下图展示一个由 list 结构和三个 listNode 节点组成的链表 Redis 的链表实现的特性可以总结如下 双端链表节点带有 prev 和 next 指针获取某个节点的前一节点和后一节点的复杂度都是 O(1)无环表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL对链表的访问以 NULL 为终点表头指针/表尾指针通过 list 结构的 head 指针和 tail 指针获取链表的表头节点和表尾节点的复杂度为 O(1)链表长度计数器通过 list 结构的 len 属性来对 list 的链表节点进行计数获取节点数量的复杂度为O(1)多态链表节点使用 void* 指针来保存节点值并通过 list 结构的 dup、free、match 三个属性为节点值设置类型特定函数所以链表可以用于保存各种不同类型的值。使用链表的附加空间相对太高因为 64bit 系统中指针是 8 个字节所以 prev 和 next 指针需要占据 16 个字节且链表节点在内存中单独分配会加剧内存的碎片化影响内存管理效率
常用命令
lpush/rpush keyvalue1value2value3 … 从左边/右边插⼊⼀个或多个值。lpop/rpop key 从左边/右边吐出⼀个值。值在键在值光键亡。rpoplpush key1key2 从 key1 列表右边吐出⼀个值插到 key2 列表左边。lrange keystartstop 按照索引下标获得元素(从左到右)lrange mylist 0 -1 0左边第⼀个-1右边第⼀个0-1表示获取所有lindex keyindex 按照索引下标获得元素(从左到右)llen key 获得列表⻓度linsert key before valuenewvalue 在 value 的后⾯插⼊值 newvaluelrem keynvalue 从左边删除 n 个 value (从左到右)lset keyindexvalue 将列表 key 下标为 index 的值替换成 value
lpush
语法lpush key value [value …]解释 将一个或多个值 value 插入到列表 key 的表头如果有多个 value 值那么各个 value 值按从左到右的顺序依次插入到表头比如说对空列表 mylist 执行命令 LPUSH mylist a b c 列表的值将是 c b a 这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。如果 key 不存在一个空列表会被创建并执行 LPUSH 操作。当 key 存在但不是列表类型时返回一个错误。注: 在 Redis 2.4 版本以前的 LPUSH 命令都只接受单个 value 值。 时间复杂度O(1)返回值执行 LPUSH 命令后列表的长度。
示例
# 加入单个元素
127.0.0.1:6379[3] LPUSH languages python
(integer) 1
# 加入重复元素
127.0.0.1:6379[3] LPUSH languages python
(integer) 2
127.0.0.1:6379[3] LRANGE languages 0 -1 # 列表允许重复元素
1) python
2) python
# 加入多个元素
127.0.0.1:6379[3] LPUSH mylist a b c
(integer) 3
127.0.0.1:6379[3] LRANGE mylist 0 -1
1) c
2) b
3) alpushx
语法lpushx key value解释 将值 value 插入到列表 key 的表头当且仅当 key 存在并且是一个列表。和 LPUSH 命令相反当 key 不存在时 LPUSHX 命令什么也不做 时间复杂度O(1)返回值LPUSHX 命令执行之后表的长度
示例
# 对空列表执行 LPUSHX
127.0.0.1:6379[3] LLEN greet # greet 是一个空列表
(integer) 0
127.0.0.1:6379[3] LPUSHX greet hello # 尝试 LPUSHX失败因为列表为空
(integer) 0
# 对非空列表执行 LPUSHX
127.0.0.1:6379[3] LPUSH greet hello # 先用 LPUSH 创建一个有一个元素的列表
(integer) 1
127.0.0.1:6379[3] LPUSHX greet good morning # 这次 LPUSHX 执行成功
(integer) 2
127.0.0.1:6379[3] LRANGE greet 0 -1
1) good morning
2) hellorpush
语法rpush key value [value …]解释 将一个或多个值 value 插入到列表 key 的表尾(最右边)。如果有多个 value 值那么各个 value 值按从左到右的顺序依次插入到表尾比如对一个空列表 mylist 执行 RPUSH mylist a b c 得出的结果列表为 a b c 等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、RPUSH mylist c。如果 key 不存在一个空列表会被创建并执行 RPUSH 操作。当 key 存在但不是列表类型时返回一个错误。注在 Redis 2.4 版本以前的 RPUSH 命令都只接受单个 value 值。 时间复杂度O(1)返回值执行 RPUSH 操作后表的长度。
示例
# 添加单个元素
127.0.0.1:6379[3] RPUSH languages c
(integer) 1
# 添加重复元素
127.0.0.1:6379[3] RPUSH languages c
(integer) 2
127.0.0.1:6379[3] LRANGE languages 0 -1 # 列表允许重复元素
1) c
2) c
# 添加多个元素
127.0.0.1:6379[3] RPUSH mylist a b c
(integer) 3
127.0.0.1:6379[3] LRANGE mylist 0 -1
1) a
2) b
3) crpushx
语法rpushx key value解释 将值 value 插入到列表 key 的表尾当且仅当 key 存在并且是一个列表。和 RPUSH 命令相反当 key 不存在时 RPUSHX 命令什么也不做。 时间复杂度O(1)返回值RPUSHX 命令执行之后表的长度
示例
# key 不存在
127.0.0.1:6379[3] LLEN greet
(integer) 0
127.0.0.1:6379[3] RPUSHX greet hello # 对不存在的 key 进行 RPUSHXPUSH 失败。
(integer) 0
# key 存在且是一个非空列表
127.0.0.1:6379[3] RPUSH greet hi # 先用 RPUSH 插入一个元素
(integer) 1
127.0.0.1:6379[3] RPUSHX greet hello # greet 现在是一个列表类型RPUSHX 操作
成功。
(integer) 2
127.0.0.1:6379[3] LRANGE greet 0 -1
1) hi
2) helloLPOP
语法lpop key解释移除并返回列表 key 的头元素。时间复杂度 O(1)返回值 列表的头元素。当 key 不存在时返回 nil 。
示例
127.0.0.1:6379[3] LLEN course
(integer) 0
127.0.0.1:6379[3] RPUSH course algorithm001
(integer) 1
127.0.0.1:6379[3] RPUSH course c101
(integer) 2
127.0.0.1:6379[3] LPOP course # 移除头元素
algorithm001RPOP
语法rpop key解释移除并返回列表 key 的尾元素。时间复杂度 O(1)返回值 列表的尾元素。当 key 不存在时返回 nil 。
示例
127.0.0.1:6379[3] RPUSH mylist one
(integer) 1
127.0.0.1:6379[3] RPUSH mylist two
(integer) 2
127.0.0.1:6379[3] RPUSH mylist three
(integer) 3
127.0.0.1:6379[3] RPOP mylist # 返回被弹出的元素
three
127.0.0.1:6379[3] LRANGE mylist 0 -1 # 列表剩下的元素
1) one
2) twoBLPOP
语法blpop key [key …] timeout解释 BLPOP 是列表的阻塞式(blocking)弹出原语。它是 LPOP 命令的阻塞版本当给定列表内没有任何元素可供弹出的时候连接将被BLPOP 命令阻塞直到等待超时或发现可弹出元素为止。当给定多个 key 参数时按参数 key 的先后顺序依次检查各个列表弹出第一个非空列表的头元素。
非阻塞行为 当 BLPOP 被调用时如果给定 key 内至少有一个非空列表那么弹出遇到的第一个非空列表的头元素并和被弹出元素所属的列表的名字一起组成结果返回给调用者。 当存在多个给定 key 时 BLPOP 按给定 key 参数排列的先后顺序依次检查各个列表。 假设现在有 job 、 command 和 request 三个列表其中 job 不存在 command 和request 都持有非空列表。考虑以下命令BLPOP job command request 0 BLPOP 保证返回的元素来自 command 因为它是按”查找 job - 查找 command - 查找 request “这样的顺序第一个找到的非空列表。 127.0.0.1:6379[3] DEL job command request # 确保 key 都被删除
(integer) 0
127.0.0.1:6379[3] LPUSH command update system... # 为 command 列表增加一个值
(integer) 1
127.0.0.1:6379[3] LPUSH request visit page # 为 request 列表增加一个值
(integer) 1
127.0.0.1:6379[3] BLPOP job command request 0 # job 列表为空被跳过紧接着command 列表的第一个元素被弹出。
1) command # 弹出元素所属的列表
2) update system... # 弹出元素所属的值阻塞行为 如果所有给定 key 都不存在或包含空列表那么 BLPOP 命令将阻塞连接直到等待超时或有另一个客户端对给定 key 的任意一个执行 LPUSH 或 RPUSH 命令为止。 超时参数 timeout 接受一个以秒为单位的数字作为值。超时参数设为 0 表示阻塞时间可以无限期延长(block indefinitely) 。 127.0.0.1:6379[3] EXISTS job # 确保两个 key 都不存在
(integer) 0
127.0.0.1:6379[3] EXISTS command
(integer) 0
127.0.0.1:6379[3] BLPOP job command 300 # 因为 key 一开始不存在所以操作会被阻塞直到另一客户端对 job 或者 command 列表进行 PUSH 操作。
1) job # 这里被 push 的是 job
2) do my home work # 被弹出的值
(26.26s) # 等待的秒数
127.0.0.1:6379[3] BLPOP job command 5 # 等待超时的情况
(nil)
(5.66s) # 等待的秒数相同的 key 被多个客户端同时阻塞
相同的 key 可以被多个客户端同时阻塞。不同的客户端被放进一个队列中按『先阻塞先服务』(first-BLPOPfirst-served)的顺序为 key 执行 BLPOP 命令。
在 MULTI/EXEC 事务中的 BLPOP BLPOP 可以用于流水线(pipline,批量地发送多个命令并读入多个回复)但把它用在MULTI / EXEC 块当中没有意义。因为这要求整个服务器被阻塞以保证块执行时的原子性该行为阻止了其他客户端执行 LPUSH 或 RPUSH 命令。 因此一个被包裹在 MULTI / EXEC 块内的 BLPOP 命令行为表现得就像 LPOP 一样对空列表返回 nil 对非空列表弹出列表元素不进行任何阻塞操作。 # 对非空列表进行操作
127.0.0.1:6379[3] RPUSH job programming
(integer) 1
127.0.0.1:6379[3] MULTI
OK
127.0.0.1:6379[3] BLPOP job 30
QUEUED
127.0.0.1:6379[3] EXEC # 不阻塞立即返回1) job2) programming
# 对空列表进行操作
127.0.0.1:6379[3] LLEN job # 空列表
(integer) 0
127.0.0.1:6379[3] MULTI
OK
127.0.0.1:6379[3] BLPOP job 30
QUEUED
127.0.0.1:6379[3] EXEC # 不阻塞立即返回
1) (nil)时间复杂度 O(1) 返回值 如果列表为空返回一个 nil 。否则返回一个含有两个元素的列表第一个元素是被弹出元素所属的 key 第二个元素是被弹出元素的值
BRPOP
语法brpop key [key …] timeout解释 BRPOP 是列表的阻塞式(blocking)弹出原语。它是 RPOP 命令的阻塞版本当给定列表内没有任何元素可供弹出的时候连接将被BRPOP 命令阻塞直到等待超时或发现可弹出元素为止。当给定多个 key 参数时按参数 key 的先后顺序依次检查各个列表弹出第一个非空列表的尾部元素。关于阻塞操作的更多信息请查看 BLPOP 命令 BRPOP 除了弹出元素的位置和 BLPOP 不同之外其他表现一致。 时间复杂度O(1)返回值 假如在指定时间内没有任何元素被弹出则返回一个 nil 和等待时长。反之返回一个含有两个元素的列表第一个元素是被弹出元素所属的 key 第二个元素是被弹出元素的值。
示例
127.0.0.1:6379[3] LLEN course
(integer) 0
127.0.0.1:6379[3] RPUSH course algorithm001
(integer) 1
127.0.0.1:6379[3] RPUSH course c101
(integer) 2
127.0.0.1:6379[3] BRPOP course 30
1) course # 弹出元素的 key
2) c101 # 弹出元素的值LLEN
语法llen key解释 返回列表 key 的长度。如果 key 不存在则 key 被解释为一个空列表返回 0 .如果 key 不是列表类型返回一个错误。 时间复杂度O(1)返回值列表 key 的长度。
示例
# 空列表
127.0.0.1:6379[3] LLEN job
(integer) 0
# 非空列表
127.0.0.1:6379[3] LPUSH job cook food
(integer) 1
127.0.0.1:6379[3] LPUSH job have lunch
(integer) 2
127.0.0.1:6379[3] LLEN job
(integer) 2LRANGE
语法lrange key start stop解释 返回列表 key 中指定区间内的元素区间以偏移量 start 和 stop 指定。下标(index)参数 start 和 stop 都以 0 为底也就是说以 0 表示列表的第一个元素以 1 表示列表的第二个元素以此类推。你也可以使用负数下标以 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推。
注意 LRANGE 命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表对该列表执行 LRANGE list 0 10 结果是一个包含 11 个元素的列表这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间)这和某些语言的区间函数可能不一致比如 Ruby 的 Range.new 、 Array#slice 和 Python的 range() 函数。
超出范围的下标
超出范围的下标值不会引起错误。如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大或者 start stop LRANGE 返回一个空列表。如果 stop 下标比 end 下标还要大Redis 将 stop 的值设置为 end 。时间复杂度O(SN) S 为偏移量 start N 为指定区间内元素的数量。返回值一个列表包含指定区间内的元素。
示例
# 空列表
127.0.0.1:6379[3] RPUSH fp-language lisp
(integer) 1
127.0.0.1:6379[3] LRANGE fp-language 0 0
1) lisp
127.0.0.1:6379[3] RPUSH fp-language scheme
(integer) 2
127.0.0.1:6379[3] LRANGE fp-language 0 1
1) lisp
2) schemeLREM
语法lrem key count value解释 根据参数 count 的值移除列表中与参数 value 相等的元素。count 的值可以是以下几种 count 0 : 从表头开始向表尾搜索移除与 value 相等的元素数量为 count 。count 0 : 从表尾开始向表头搜索移除与 value 相等的元素数量为 count 的绝对值。count 0 : 移除表中所有与 value 相等的值。 时间复杂度O(N) N 为列表的长度。返回值被移除元素的数量。因为不存在的 key 被视作空表(empty list)所以当 key 不存在时 LREM 命令总是返回 0 。
示例
# 空列表
# 先创建一个表内容排列是
# morning hello morning helllo morning
127.0.0.1:6379[3] LPUSH greet morning
(integer) 1
127.0.0.1:6379[3] LPUSH greet hello
(integer) 2
127.0.0.1:6379[3] LPUSH greet morning
(integer) 3
127.0.0.1:6379[3] LPUSH greet hello
(integer) 4
127.0.0.1:6379[3] LPUSH greet morning
(integer) 5
127.0.0.1:6379[3] LRANGE greet 0 4 # 查看所有元素
1) morning
2) hello
3) morning
4) hello
5) morning
127.0.0.1:6379[3] LREM greet 2 morning # 移除从表头到表尾最先发现的两个 morning
(integer) 2 # 两个元素被移除
127.0.0.1:6379[3] LLEN greet # 还剩 3 个元素
(integer) 3
127.0.0.1:6379[3] LRANGE greet 0 2
1) hello
2) hello
3) morning
127.0.0.1:6379[3] LREM greet -1 morning # 移除从表尾到表头第一个 morning
(integer) 1
127.0.0.1:6379[3] LLEN greet # 剩下两个元素
(integer) 2
127.0.0.1:6379[3] LRANGE greet 0 1
1) hello
2) hello
127.0.0.1:6379[3] LREM greet 0 hello # 移除表中所有 hello
(integer) 2 # 两个 hello 被移除
127.0.0.1:6379[3] LLEN greet
(integer) 0LSET
语法lset key index value解释 将列表 key 下标为 index 的元素的值设置为 value 。当 index 参数超出范围或对一个空列表( key 不存在)进行 LSET 时返回一个错误。关于列表下标的更多信息请参考 LINDEX 命令。 时间复杂度对头元素或尾元素进行 LSET 操作复杂度为 O(1)。其他情况下为 O(N) N 为列表的长度。返回值操作成功返回 ok 否则返回错误信息。
示例
# 对空列表(key 不存在)进行 LSET
127.0.0.1:6379[3] EXISTS list
(integer) 0
127.0.0.1:6379[3] LSET list 0 item
(error) ERR no such key
# 对非空列表进行 LSET
127.0.0.1:6379[3] LPUSH job cook food
(integer) 1
127.0.0.1:6379[3] LRANGE job 0 0
1) cook food
127.0.0.1:6379[3] LSET job 0 play game
OK
127.0.0.1:6379[3] LRANGE job 0 0
1) play game
# index 超出范围
127.0.0.1:6379[3] LLEN list # 列表长度为 1
(integer) 1
127.0.0.1:6379[3] LSET list 3 out of range
(error) ERR index out of rangeLTRIM
语法ltrim key start stop解释 对一个列表进行修剪(trim)就是说让列表只保留指定区间内的元素不在指定区间之内的元素都将被删除。举个例子执行命令 LTRIM list 0 2 表示只保留列表 list 的前三个元素其余元素全部删除。下标(index)参数 start 和 stop 都以 0 为底也就是说以 0 表示列表的第一个元素以 1 表示列表的第二个元素以此类推。你也可以使用负数下标以 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推。当 key 不是列表类型时返回一个错误。LTRIM 命令通常和 LPUSH 命令或 RPUSH 命令配合使用举个例子LPUSH log newest_log
LTRIM log 0 99这个例子模拟了一个日志程序每次将最新日志 newest_log 放到 log 列表中并且只保留最新的 100 项。注意当这样使用 LTRIM 命令时时间复杂度是 O(1)因为平均情况下每次只有一个元素被移除。
注意 LTRIM 命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表 list 对该列表执行 LTRIM list 0 10 结果是一个包含 11 个元素的列表这表明 stop 下标也在 LTRIM 命令的取值范围之内(闭区间)这和某些语言的区间函数可能不一致比如 Ruby 的 Range.new 、 Array#slice 和 Python的 range() 函数。
超出范围的下标 超出范围的下标值不会引起错误。 如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大或者 start stop LTRIM 返回一个空列表(因为 LTRIM 已经将整个列表清空)。 如果 stop 下标比 end 下标还要大Redis 将 stop 的值设置为 end 。 时间复杂度O(N) N 为被移除的元素的数量。 返回值命令执行成功时返回 ok 。
示例
# 一般情况下标
127.0.0.1:6379[3] LRANGE alpha 0 -1 # 建立一个 5 元素的列表
1) h
2) e
3) l
4) l
5) o
127.0.0.1:6379[3] LTRIM alpha 1 -1 # 删除索引为 0 的元素
OK
127.0.0.1:6379[3] LRANGE alpha 0 -1 # h 被删除
1) e
2) l
3) l
4) o
# stop 下标比元素的最大下标要大
127.0.0.1:6379[3] LTRIM alpha 1 10086
OK
127.0.0.1:6379[3] LRANGE alpha 0 -1
1) l
2) l
3) o
# start 和 stop 下标都比最大下标要大且 start sotp
127.0.0.1:6379[3] LTRIM alpha 10086 200000
OK
127.0.0.1:6379[3] LRANGE alpha 0 -1 # 整个列表被清空等同于 DEL alpha
(empty list or set)
# start stop
127.0.0.1:6379[3] LRANGE alpha 0 -1 # 在新建一个列表
1) h
2) u
3) a
4) n
5) g
6) z
127.0.0.1:6379[3] LTRIM alpha 10086 4
OK
127.0.0.1:6379[3] LRANGE alpha 0 -1 # 列表同样被清空
(empty list or set)LINDEX
语法lindex key index解释 返回列表 key 中下标为 index 的元素。下标(index)参数 start 和 stop 都以 0 为底也就是说以 0 表示列表的第一个元素以 1 表示列表的第二个元素以此类推。你也可以使用负数下标以 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推。如果 key 不是列表类型返回一个错误。 时间复杂度 O(N) N 为到达下标 index 过程中经过的元素数量。因此对列表的头元素和尾元素执行 LINDEX 命令复杂度为 O(1)。 返回值 列表中下标为 index 的元素。如果 index 参数的值不在列表的区间范围内(out of range)返回 nil 。
示例
127.0.0.1:6379[3] LPUSH mylist World
(integer) 1
127.0.0.1:6379[3] LPUSH mylist Hello
(integer) 2
127.0.0.1:6379[3] LINDEX mylist 0
Hello
127.0.0.1:6379[3] LINDEX mylist -1
World
127.0.0.1:6379[3] LINDEX mylist 3 # index 不在 mylist 的区间范围内
(nil)LINSERT
语法linsert key BEFORE|AFTER pivot value解释 将值 value 插入到列表 key 当中位于值 pivot 之前或之后。当 pivot 不存在于列表 key 时不执行任何操作。当 key 不存在时 key 被视为空列表不执行任何操作。如果 key 不是列表类型返回一个错误。 时间复杂度O(N) N 为寻找 pivot 过程中经过的元素数量。返回值 如果命令执行成功返回插入操作完成之后列表的长度。如果没有找到 pivot 返回 -1 。如果 key 不存在或为空列表返回 0
示例
127.0.0.1:6379[3] RPUSH mylist Hello
(integer) 1
127.0.0.1:6379[3] RPUSH mylist World
(integer) 2
127.0.0.1:6379[3] LINSERT mylist BEFORE World There
(integer) 3
127.0.0.1:6379[3] LRANGE mylist 0 -1
1) Hello
2) There
3) World
# 对一个非空列表插入查找一个不存在的 pivot
127.0.0.1:6379[3] LINSERT mylist BEFORE go lets
(integer) -1 # 失败
# 对一个空列表执行 LINSERT 命令
127.0.0.1:6379[3] EXISTS fake_list
(integer) 0
127.0.0.1:6379[3] LINSERT fake_list BEFORE nono gogogog
(integer) 0 # 失败RPOPLPUSH
语法rpoplpush source destination解释 命令 RPOPLPUSH 在一个原子时间内执行以下两个动作 将列表 source 中的最后一个元素(尾元素)弹出并返回给客户端。将 source 弹出的元素插入到列表 destination 作为 destination 列表的的头元素。 举个例子你有两个列表 source 和 destination source 列表有元素 a, b, c destination 列表有元素 x, y, z 执行 RPOPLPUSH source destination 之后 source 列表包含元素 a, b destination 列表包含元素 c, x, y, z 并且元素 c 会被返回给客户端。 如果 source 不存在值 nil 被返回并且不执行其他动作。如果 source 和 destination 相同则列表中的表尾元素被移动到表头并返回该元素可以把这种特殊情况视作列表的旋转(rotation)操作。 时间复杂度O(1)返回值被弹出的元素。
示例
# source 和 destination 不同
127.0.0.1:6379[3] LRANGE alpha 0 -1 # 查看所有元素
1) a
2) b
3) c
4) d
127.0.0.1:6379[3] RPOPLPUSH alpha reciver # 执行一次 RPOPLPUSH 看看
d
127.0.0.1:6379[3] LRANGE alpha 0 -1
1) a
2) b
3) c
127.0.0.1:6379[3] LRANGE reciver 0 -1
1) d
127.0.0.1:6379[3] RPOPLPUSH alpha reciver # 再执行一次证实 RPOP 和 LPUSH 的位置正确
c
127.0.0.1:6379[3] LRANGE alpha 0 -1
1) a
2) b
127.0.0.1:6379[3] LRANGE reciver 0 -1
1) c
2) d
# source 和 destination 相同
127.0.0.1:6379[3] LRANGE number 0 -1
1) 1
2) 2
3) 3
4) 4
127.0.0.1:6379[3] RPOPLPUSH number number
4
127.0.0.1:6379[3] LRANGE number 0 -1 # 4 被旋转到了表头
1) 4
2) 1
3) 2
4) 3
127.0.0.1:6379[3] RPOPLPUSH number number
3
127.0.0.1:6379[3] LRANGE number 0 -1 # 这次是 3 被旋转到了表头
1) 3
2) 4
3) 1
4) 2应用1安全的队列
Redis 的列表经常被用作队列(queue)用于在不同程序之间有序地交换消息(message)。一个客户端通过 LPUSH 命令将消息放入队列中而另一个客户端通过 RPOP 或者 BRPOP 命令取出队列中等待时间最长的消息。不幸的是上面的队列方法是『不安全』的因为在这个过程中一个客户端可能在取出一个消息之后崩溃而未处理完的消息也就因此丢失。使用 RPOPLPUSH 命令(或者它的阻塞版本 BRPOPLPUSH )可以解决这个问题因为它不仅返回一个消息同时还将这个消息添加到另一个备份列表当中如果一切正常的话当一个客户端完成某个消息的处理之后可以用 LREM 命令将这个消息从备份表删除。最后还可以添加一个客户端专门用于监视备份表它自动地将超过一定处理时限的消息重新放入队列中去(负责处理该消息的客户端可能已经崩溃)这样就不会丢失任何消息了。
应用2循环列表
通过使用相同的 key 作为 RPOPLPUSH 命令的两个参数客户端可以用一个接一个地获取列表元素的方式取得列表的所有元素而不必像 LRANGE 命令那样一下子将所有列表元素都从服务器传送到客户端中(两种方式的总复杂度都是 O(N))。以上的模式甚至在以下的两个情况下也能正常工作 有多个客户端同时对同一个列表进行旋转(rotating)它们获取不同的元素直到所有元素都被读取完之后又从头开始。有客户端在向列表尾部(右边)添加新元素。 这个模式使得我们可以很容易实现这样一类系统有 N 个客户端需要连续不断地对一些元素进行处理而且处理的过程必须尽可能地快。一个典型的例子就是服务器的监控程序 它们需要在尽可能短的时间内并行地检查一组网站确保它们的可访问性。 注意使用这个模式的客户端是易于扩展(scala)且安全(reliable)的因为就算接收到元素的客户端失败元素还是保存在列表里面不会丢失等到下个迭代来临的时候别的客户端又可以继续处理这些元素了。
BRPOPLPUSH
语法brpoplpush source destination timeout解释 BRPOPLPUSH 是 RPOPLPUSH 的阻塞版本当给定列表 source 不为空时 BRPOPLPUSH的表现和 RPOPLPUSH 一样。当列表 source 为空时 BRPOPLPUSH 命令将阻塞连接直到等待超时或有另一个客户端对 source 执行 LPUSH 或 RPUSH 命令为止。超时参数 timeout 接受一个以秒为单位的数字作为值。超时参数设为 0 表示阻塞时间可以无限期延长(block indefinitely) 。更多相关信息请参考 RPOPLPUSH 命令。 时间复杂度O(1)返回值 假如在指定时间内没有任何元素被弹出则返回一个 nil 和等待时长。反之返回一个含有两个元素的列表第一个元素是被弹出元素的值第二个元素是等待时长。
示例
# 非空列表
127.0.0.1:6379[3] BRPOPLPUSH msg reciver 500
hello moto # 弹出元素的值
(3.38s) # 等待时长
127.0.0.1:6379[3] LLEN reciver
(integer) 1
127.0.0.1:6379[3] LRANGE reciver 0 0
1) hello moto
# 空列表
127.0.0.1:6379[3] BRPOPLPUSH msg reciver 1
(nil)
(1.34s)应用1安全队列
参考 RPOPLPUSH 命令的『安全队列』模式。
应用2循环列表
参考 RPOPLPUSH 命令的『循环列表』模式