(4)Redis 数据结构(List的操作)
第四节:Redis 数据结构之List 类型
存储list:
ArrayList使用数组方式
LinkedList使用双向链接方式
双向链接表中增加数据
双向链接表中删除数据
存储list常用命令
两端添加
两端弹出
扩展命令
下面是操作命令的例子:
lpush 方式从左边开始添加
127.0.0.1:6379> lpush list1 a b c d (integer) 4 127.0.0.1:6379> lpush list1 1 2 3 4 (integer) 8 127.0.0.1:6379> lrange list1 0 -1 1) "4" 2) "3" 3) "2" 4) "1" 5) "d" 6) "c" 7) "b" 8) "a" 127.0.0.1:6379> lrange list1 0 4 1) "4" 2) "3" 3) "2" 4) "1" 5) "d"
lrange索引下标特点:从左到右为0到n-1
lrange 0 -1 命令可以从左到右获取列表的所有元素
rpush 从右端开始添加(一般人比较习惯这种方式)
127.0.0.1:6379> rpush list2 a b c d (integer) 4 127.0.0.1:6379> rpush list2 1 2 3 4 (integer) 8 127.0.0.1:6379> lrange list2 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "1" 6) "2" 7) "3" 8) "4"
rpop 右侧弹出集合元素
127.0.0.1:6379> lrange list2 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379> rpop list2
"4"
127.0.0.1:6379> lrange list2 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
lpop 左侧弹出集合元素
127.0.0.1:6379> lrange list2 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
127.0.0.1:6379> lpop list2
"a"
127.0.0.1:6379> lrange list2 0 -1
1) "b"
2) "c"
3) "d"
4) "1"
5) "2"
6) "3"
自评:关于lpush、rpush、lpop、rpop的使用问题
比如rpush按顺序添加a b c d四个元素,添加完之后元素存放位置如下:
a b c d
这时候,如果:
lpop: 返回a,先进先出
rpop: 返回d,先进后出
项目中有个权益券码的保存和使用是这样的:
1.存在toolList:tool1, tool2, tool3
2.插入数据库后顺序是:tool3,tool2, tool1
2.使用rightPushAll: tool1, tool2, tool3
3.push完成之后key的值:equity:stock:equityId_001 - [tool1, tool2, tool3]
4.lpop消费1个返回:tool1
这样是先入库的后消费了。
llen查看元素个数
127.0.0.1:6379> llen list2
(integer) 6
lpushx 集合头部插入元素
127.0.0.1:6379> lrange list2 0 -1
1) "b"
2) "c"
3) "d"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> lpushx list2 zhangsan
(integer) 7
127.0.0.1:6379> lrange list2 0 -1
1) "zhangsan"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
rpushx 集合尾部插入元素
127.0.0.1:6379> lrange list2 0 -1
1) "zhangsan"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
127.0.0.1:6379> rpushx list2 lisi
(integer) 8
127.0.0.1:6379> lrange list2 0 -1
1) "zhangsan"
2) "b"
3) "c"
4) "d"
5) "1"
6) "2"
7) "3"
8) "lisi"
lpush集合头部插入多个元素
rpush集合尾部插入多个元素
127.0.0.1:6379> lrange list2 0 -1
1) "b"
2) "c"
3) "d"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> lpush list2 a1 a2
(integer) 8
127.0.0.1:6379> lrange list2 0 -1
1) "a2"
2) "a1"
3) "b"
4) "c"
5) "d"
6) "1"
7) "2"
8) "3"
127.0.0.1:6379> lrange list2 0 -1
1) "b"
2) "c"
3) "d"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> rpush list2 zhangsan lisi
(integer) 8
127.0.0.1:6379> lrange list2 0 -1
1) "b"
2) "c"
3) "d"
4) "1"
5) "2"
6) "3"
7) "zhangsan"
8) "lisi"
lpush和lpushx的区别:
核心区别在于:当键key不存在时,它们的行为完全不同。LPUSH会总是创建一个新列表并插入元素,而LPUSHX则只在列表已存在时才插入元素,否则什么也不做。
这个规则同样适用于rpush和rpushx
Redis List作为消息队列或任务队列的经典用法:
使用RPUSH(从右端生产) + LPOP(从左端消费)组合,完美实现了先进先出(FIFO)的顺序。
#生产者(存入):使用RPUSH将券码依次从列表右侧推入。
RPUSH voucher_queue "codeA" "codeB" "codeC" # 此时列表为:["codeA", "codeB", "codeC"]
# 消费者(取出):使用LPOP从列表左侧弹出。
"codeA" # 第一次LPOP取出"codeA",列表变为["codeB", "codeC"]
但是生产环境必须解决的两个问题:
1.并发消费导致同一券码被多次领取(竞争条件)
-
场景:两个消费者(如两台服务器上的程序)同时执行
LPOP。 -
风险:虽然
LPOP本身是原子操作(不会取出同一个元素两次),但如果在“取出券码”和“标记已使用”之间发生了网络延迟或程序崩溃,这个券码可能已经从队列移除但未被成功核销,导致券码丢失。
2.消费者崩溃导致正在处理的券码永久丢失
-
场景:消费者用
LPOP取出了券码A,但在核销A的过程中(比如调用第三方接口)服务器突然宕机。 -
风险:A已经从队列中永久移除,但核销未完成,这张券永远无法被再次消费,造成资损。
生产级解决方案:使用 RPOPLPUSH 或 BRPOPLPUSH
lrem 从指定方向删除指定个数的指定元素
127.0.0.1:6379> lpush list4 1 3 2 3 2 1 2 1 3
(integer) 9
127.0.0.1:6379> lrange list4 0 -1
1) "3"
2) "1"
3) "2"
4) "1"
5) "2"
6) "3"
7) "2"
8) "3"
9) "1"
从左边开始删除2个1
127.0.0.1:6379> lrem list4 2 1
(integer) 2
127.0.0.1:6379> lrange list4 0 -1
1) "3"
2) "2"
3) "2"
4) "3"
5) "2"
6) "3"
7) "1"
从右边开始删除2个3
127.0.0.1:6379> lrem list4 -2 3 (integer) 2 127.0.0.1:6379> lrange list4 0 -1 1) "3" 2) "2" 3) "2" 4) "2" 5) "1"
删除所有2
127.0.0.1:6379> lrem list4 0 2 (integer) 3 127.0.0.1:6379> lrange list4 0 -1 1) "3" 2) "1"
lset 设置集合指定索引的值
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "d"
6) "c"
7) "b"
8) "a"
127.0.0.1:6379> lset list1 3 xxxx
OK
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "xxxx"
5) "d"
6) "c"
7) "b"
8) "a"
linsert 在集合里插入指定元素
在xxxx元素之前插入aa
127.0.0.1:6379> linsert list1 before xxxx aa
(integer) 9
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "aa"
5) "xxxx"
6) "d"
7) "c"
8) "b"
9) "a"
在xxxx元素之后插入bb
127.0.0.1:6379> linsert list1 after xxxx bb
(integer) 10
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "aa"
5) "xxxx"
6) "bb"
7) "d"
8) "c"
9) "b"
10) "a"
rpoplpush 把A集合尾部元素弹出并插入到B集合头部
127.0.0.1:6379> rpush list5 a b c (integer) 3 127.0.0.1:6379> rpush list6 1 2 3 (integer) 3 127.0.0.1:6379> rpoplpush list5 list6 "c" 127.0.0.1:6379> lrange list5 0 -1 1) "a" 2) "b" 127.0.0.1:6379> lrange list6 0 -1 1) "c" 2) "1" 3) "2" 4) "3"
浙公网安备 33010602011771号