Redis中的List类型
目录
List类型的命令
lpush
lpushx
rpush
lrange
lpop
rpop
lindex
linsert
llen
lrem
ltrim
lset
阻塞命令
阻塞命令的使用场景
1.针对一个非空的列表进行操作
2.针对一个空的列表进行操作
3.针对多个key进行操作.
内部编码
lisi类型的应用场景
存储(班级)信息
消息队列
分频道的消息队列
微博Timeline
列表(List)相当于是数组或者是顺序表.
结构示意图
约定最左侧的元素下标是0,redis的下标支持负数下标.
注意list内部的编码方式并非是一个简单的数组,而是更接近于双端队列.
列表中的元素是有序的,指的并不是其按照元素的数据大小进行排列,而是意味着当你向列表中插入元素时,它们会按照插入的顺序进行排序(比如尾插abc,得到的列表也是abc),并且每个元素都有一个关联的索引值来表示其位置。
列表中的元素是允许重复的.
List类型的命令
lpush
将一个或者多个元素从左侧放入到list中.(头插)
LPUSH key element [element ...]
时间复杂度是O(N),N代表插入元素的个数.
lpushx
当key存在时,将一个或者多个元素从左侧放入到list中,不存在则直接返回.
x->exists.
LPUSHX key element [element ...]

rpush
将一个或者多个元素从右侧放入到list中,尾插.
RPUSH key element [element...........]
时间复杂度是O(N),N代表插入元素的个数.
rpushx,类似与lpushx,尾插,不存在直接返回.
lrange
LRANGE key start stop
对于超出下标的情况,redis会尽可能的获取对应的内容.
lpop
LPOP key
从list左侧取出元素,即头删.
返回的是取出的元素或者nil.
rpop
从list右侧取出元素,尾删.
RPOP key

lindex
LINDEX key index
获取从左数第index位置的元素.
时间复杂度是O(N),N指的是list中元素的个数.
返回的是取出的元素或者是nil.
linsert
LINSERT key <BEFORE | AFTER> pivot element
返回的是插入后list的长度.
时间复杂度是O(N).N代表列表的长度.
如果进行插入的时候,基准值有多个,redis是从左往右找,找到第一个符合基准值的位置.
llen
获取list的长度.
LLEN key
时间复杂度是O(1).
时间复杂度为什么是O(1):这是因为Redis将列表的长度存储在列表对象的内部数据结构中,并且在每次插入或删除元素时都会更新该长度。因此,当执行LLEN命令时,Redis可以直接返回列表的长度,无需遍历整个列表,所以时间复杂度是固定的,与列表的长度无关。
lrem
lrem key count element
count表示要删除的个数,element表示要删除的值.
当count>0时表示从左向右删除元素.
当count<0时表示从右向左删除元素.
当count=0时表示删除全部指定元素.
ltrim
LTRIM key start stop
保留start和stop之间区间内的元素,区间外面的元素就直接被删除了.
lset
LSET key index element
根据下标修改元素.
时间复杂度:O(N).
如果下标越界会直接报错.
阻塞命令
blpop key [key.....] timeout
brpop key [key.....] timeout
blpop和brpop是lpop和rpop的阻塞版本.
相当于我们之前学习的阻塞队列一样.
当队列元素为满的时候,在往里插入元素会阻塞;当队列元素为空的时候,往外取元素也会阻塞.
redis只针对队列为空往外取的时候做了阻塞.因为redis中对于list什么时候为满没有明确的要求.
所以blpop和brpop.
blpop和brpop是lpop和rpop的阻塞版本,和对应的非阻塞版本的作用基本一致,除了:
1.在列表有元素的情况下,阻塞和非阻塞版本表现一致.但是如果列表为空,非阻塞版本会立即执行并返回nil,但阻塞版本会根据timeout阻塞一段时间,期间redis可以执行其他命令,但执行阻塞命令的客户端会表现为阻塞状态.
2.命令中如果设置了多个键,那么会从左向右进行遍历键,一旦有一个键对应的列表可以弹出元素,命令立即返回.
3.如果多个客户端对一个键执行brpop或blpop,最先执行命令的客户端会得到弹出的元素.
阻塞命令的使用场景
1.针对一个非空的列表进行操作
返回的结果是一个二元组,一方面告诉我们当前的数据来自哪个key,一方面告诉我们取到的数据是什么.
2.针对一个空的列表进行操作
返回二元组并且显示阻塞时间.
3.针对多个key进行操作.
内部编码
之前的版本list的内部编码是ziplist(压缩列表)和linkedlist(链表).
和hash类型的类似,当元素个数过多的时候,ziplist会转换为linkedlist;当某个value过长的时候,ziplist也会转换为linkedList.
同样也存在两个配置项:list-max-ziplist-entries和list-max-ziplist-value.
而现在的版本list的内部编码只有一个quicklist.
quicklist相当于是结合了链表和压缩列表.
整体还是一个链表,但是链表的每一个节点是一个压缩列表.
每个压缩列表都不要太大,同时再把多个压缩列表通过链式结构的方式连接起来.
lisi类型的应用场景
存储(班级)信息
用list作为像数组这样的结构,来存储多个元素.
用mysql表示两个表,一个学生表一个班级表.
通过这样的表结构,可以很方便的实现查询指定班级中有哪些同学.
而redis中没有这么强调的查询功能,我们只能设置合适的键值对来实现对应的效果.
学生的个人信息用hash表示,而班级信息我们就可以使用list类型来表示.
通过classStudent:1来获取对应的学生id.
消息队列
redis阻塞消息的队列模型
在当前的场景下,如果列表为空,消费者就会阻塞等待,直到有了数据或者到了timeout时间.
谁先执行brpop命令,谁就可以先拿到新来的数据.
如果消费者不停的brpop,这样的设定就能构成一个轮询的效果.
分频道的消息队列
多个频道的场景非常常见,比如一个短视频,可以有一个频道来传输短视频数据,还可以有一个频道来传输弹幕数据,还可以有一个频道来传输点赞,转发和收藏的数据,可以有一个频道来传输评论数据.
设置成多个频道,就可以在某种数据发生问题的时候,不会对其他数据造成影响.
微博Timeline
1.每篇微博使用hash结构存储.
2.向用户的timeline添加微博.user:<uid>:myblogs作为键.
3.分页获取用户的timeline,例如获取用户1的10篇微博.