一.简介
- Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
- 一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
- 类似JAVA中的LinkedList
二.基本命令
赋值语法:
LPUSH key value1 [value2] //将一个或多个值插入到列表头部(从左侧添加)
RPUSH key value1 [value2] //在列表中添加一个或多个值(从右侧添加)
LPUSHX key value //将一个值插入到已存在的列表头部。如果列表不在,操作无效
RPUSHX key value //一个值插入已存在的列表尾部(最右边)。如果列表不在,操作无效。
例子:新建一个list,名字叫emplist,有三个值分别是三个员工名字:
127.0.0.1:6379> lpush emplist xiaoming xiaohong xiaoli
(integer) 3 //插入成功
127.0.0.1:6379> lrange emplist 0 -1
1) "xiaoli"
2) "xiaohong"
3) "xiaoming"
因为是从左侧添加(相当于从链表头部插入),所以结果是从xiaoli开始的
取值语法:
LLEN key //获取列表长度
LINDEX key index //通过索引获取列表中的元素
LRANGE key start stop //获取列表指定范围内的元素
跟python列表语法类似,第n个元素的索引是n-1,如果是-1那么就是最后一个。-2就是倒数第二个。。。
//首先看看emplist的长度
127.0.0.1:6379> llen emplist
(integer) 3
//查询emplist中倒数第一个元素的值
127.0.0.1:6379> lindex emplist -1
"xiaoming"
删除语法
LPOP key //移出并获取列表的第一个元素(从左侧删除)
RPOP key //移除列表的最后一个元素,返回值为移除的元素(从右侧删除)
BLPOP key1 [key2 ] timeout
--移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
对于最后一个命令,可用于多线程并发的情况下,设置timeout(单位为ms),如果没有则阻塞等待
修改语法:
LSET key index value --通过索引设置列表元素的值
LINSERT key BEFORE|AFTER world value
--在列表的元素前或者后插入元素
--描述:将值 value 插入到列表 key 当中,位于值 world 之前或之后
现在想在xiaoli,xiaohong两人之间插入一个新的员工xiaowang:
127.0.0.1:6379> linsert emplist before xiaohong xiaowang
(integer) 4
//插入成功 显示一下!
127.0.0.1:6379> lrange emplist 0 -1
1) "xiaoli"
2) "xiaowang"
3) "xiaohong"
4) "xiaoming"
三.高级语法
RPOPLPUSH source destination
//移除列表的最后一个元素,并将该元素添加到另一个列表并返回
//示例描述:
RPOPLPUSH a1 a2 //a1的最后元素移到a2的左侧
RPOPLPUSH a1 a1 //循环列表,将最后元素移到最左侧
BRPOPLPUSH source destination timeout
//从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
这里先不用例,下面应用场景会提到
四.应用场景
- 对数据量大的集合数据删减
- 列表数据显示、关注列表、粉丝列表、留言评价等…分页、热点新闻(Top5)等
- 利用LRANGE还可以很方便的实现分页的功能,在博客系统中,每片博文的评论也可以存入一个单独的list中
- 任务队列
- list通常用来实现一个消息队列,而且可以确保先后顺序,不必像MySQL那样还需要通过ORDER BY来进行排序
案例:物流变化状态
例如这里有一个快递要从北京发往上海:途中要经过北京机场---->飞机---->上海机场---->汽车----->大别墅
首先我们创建一个list,将这些状态都push进队列:
127.0.0.1:6379> lpush ems beijing fahuo jichang feiji shanghaijichang qiche dabieshu
(integer) 7
一般来说我们都能看到当前快递的状态,也就是说有一个list来保存还没有完成的状态,比如现在已经在飞机上了,那么beijing fahuo jichang这三个状态肯定已经没有了。
核心就是用RPOPLPUSH source destination 方法
127.0.0.1:6379> lrange ems 0 -1
1) "dabieshu"
2) "qiche"
3) "shanghaijichang"
4) "feiji"
5) "jichang"
6) "fahuo"
7) "beijing"
127.0.0.1:6379> rpoplpush ems finish
"beijing"
127.0.0.1:6379> rpoplpush ems finish
"fahuo"
127.0.0.1:6379> rpoplpush ems finish
"jichang"
可以看到这边我进行了三次相同的操作,这就类似于快递员送货的过程,货物每到一个地点就会通知服务器更新状态,下面看下结果:
127.0.0.1:6379> lrange ems 0 -1
1) "dabieshu"
2) "qiche"
3) "shanghaijichang"
4) "feiji"
这样的话,我们打开手机查物流就能查到当前的状态是:feiji 在飞机上 (顺序不要在意,因为直接把list反转就可以顺序输出了)
为什么只有RPOPLPUSH 没有 LPOPRPUSH?
- 查不到啊,redis底层是一个双向链表,那么理论上可以进行lpoprpush的