网站免费建站广告机,360建筑网发布的简历,网站设计制作上海,网站怎么发内容优化List-列表类型:LR 列表类型#xff1a;有序、可重复 Arraylist和linkedlist的区别 Arraylist是使用数组来存储数据#xff0c;特点#xff1a;查询快、增删慢 Linkedlist是使用双向链表存储数据#xff0c;特点#xff1a;增删快、查询慢#xff0c;但是查询链表两端… List-列表类型:LR 列表类型有序、可重复 Arraylist和linkedlist的区别 Arraylist是使用数组来存储数据特点查询快、增删慢 Linkedlist是使用双向链表存储数据特点增删快、查询慢但是查询链表两端的数据也很快。 Redis的list是采用来链表来存储的所以对于redis的list数据类型的操作是操作list的两端数据来操作的。 命令 向列表左边增加元素:lpush key:val1 val2 127.0.0.1:6379lpush list:1 1 2 3 (integer) 3 向列表右边增加元素:rpush key:val1 val2 127.0.0.1:6379rpush list:1 4 5 6 (integer) 3 查看列表:LRANGE key start stop LRANGE命令是列表类型最常用的命令之一获取列表中的某一片段将返回start、stop之间的所有元素(包含两端的元素)索引从0开始。索引可以是负数如“-1”代表最后边的一个元素。 语法LRANGE key start stop 获取下标0-2的元素 前闭后闭 127.0.0.1:6379 lrange list1 0 2 1) 2 2) 1 3) 4 这里需要注意的是list的索引从0开始大家知道但是取全部list的值时结束索引需要设置为-1也可以设置成list长度减1 127.0.0.1:6379 lrange l:list 0 -1 1) 6 2) 5 3) 2 4) 2 从列表两端弹出元素:LPOP keyRPOP key LPOP命令从列表左边弹出一个元素会分两步完成 第一步是将列表左边的元素从列表中移除 第二步是返回被移除的元素值。 语法 LPOP key RPOP key 127.0.0.1:6379 lpop list:1 3“ 127.0.0.1:6379 rpop list:1 6“ 获取列表中元素的个数LLEN key 语法LLEN key 127.0.0.1:6379 llen list:1 (integer) 2 删除列表中指定的值 LREM key count value LREM命令会删除列表中前count个值为value的元素返回实际删除的元素个数。根据count值的不同该命令的执行方式会有所不同 当count0时 LREM会从列表左边开始删除。 当count0时 LREM会从列表后边开始删除。 当count0时 LREM删除所有值为value的元素。 删除2个值为1的元素 语法LREM key count value 127.0.0.1:6379 lrem list1 2 1 (integer) 2 获得/设置指定索引的元素值LINDEX key index 获得指定索引的元素值 语法LINDEX key index 127.0.0.1:6379 lindex list 2 1 设置指定索引的元素值 语法LSET key index value 127.0.0.1:6379 lset list 2 2 OK 只保留列表指定范围元素:LTRIM key start stop 只保留start - stop 之间的元素 语法LTRIM key start stop 127.0.0.1:6379 lrange l:list 0 -1 1) 6 2) 5 3) 0 4) 2 127.0.0.1:6379 ltrim l:list 0 2 OK 127.0.0.1:6379 lrange l:list 0 -1 1) 6 2) 5 3) 0 向列表中插入元素LINSERT key BEFORE|AFTER pivot value 该命令首先会在列表中从左到右查找值为pivot的元素然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。 语法LINSERT key BEFORE|AFTER pivot value 127.0.0.1:6379 lrange list 0 -1 1) 3 2) 2 3) 1 将值为4的元素插入到3后面 127.0.0.1:6379 linsert list after 3 4 (integer) 4 127.0.0.1:6379 lrange list 0 -1 1) 3 2) 4 3) 2 4) 1 将A列表最后一个元素移到B列表RPOPLPUSH source destination 用于移除列表的最后一个元素并将该元素添加到另一个列表并返回。 语法RPOPLPUSH source destination 127.0.0.1:6379 lrange list 0 -1 1) 3 2) 4 3) 2 4) 1 127.0.0.1:6379 rpoplpush list newlist 1 127.0.0.1:6379 lrange newlist 0 -1 1) 1 127.0.0.1:6379 lrange list 0 -1 1) 3 2) 4 3) 2 移出并获取列表的最后一个元素(阻塞):Brpop 移出并获取列表的最后一个元素 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 redis 127.0.0.1:6379 BRPOP LIST1 LIST2 .. LISTN TIMEOUT 假如在指定时间内没有任何元素被弹出则返回一个 nil 和等待时长。 反之返回一个含有两个元素的列表第一个元素是被弹出元素所属的 key 第二个元素是被弹出元素的值。 redis DEL list1 list2 (integer) 0 redis RPUSH list1 a b c (integer) 3 redis BRPOP list1 list2 0 1) list1 2) c 将A列表最后一个元素移到B列表(阻塞)Brpoplpush 命令从列表中取出最后一个元素并插入到另外一个列表的头部 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。假如在指定时间内没有任何元素被弹出则返回一个 nil 和等待时长。 反之返回一个含有两个元素的列表第一个元素是被弹出元素的值第二个元素是等待时长。 redis 127.0.0.1:6379 BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT 非空列表 redis BRPOPLPUSH msg reciver 500 hello moto # 弹出元素的值 (3.38s) # 等待时长 redis LLEN reciver (integer) 1 redis LRANGE reciver 0 0 1) hello moto 空列表 redis BRPOPLPUSH msg reciver 1 (nil) (1.34s) 应用场景:大容量更新频率不高的静态列表 商品评论列表 思路 在Redis中创建商品评论列表 用户发布商品评论将评论信息转成json存储到list中。 用户在页面查询评论列表从redis中取出json数据展示到页面。 定义商品评论列表key 商品编号为1001的商品评论key【items: comment:1001】 每日排行榜:某个时间段数据固定榜单 list类型的lrange命令可以分页查看队列中的数据。可将每隔一段时间计算一次的排行榜存储在list类型中如京东每日的手机销量排行、学校每次月考学生的成绩排名、斗鱼年终盛典主播排名等下图是酷狗音乐“K歌擂台赛”的昨日打擂金曲排行榜每日计算一次存储在list类型中接口访问时通过page和size分页获取打擂金曲。 list类型的lpush命令和lrange命令能实现最新列表的功能每次通过lpush命令往列表里插入新的元素然后通过lrange命令读取最新的元素列表如朋友圈的点赞列表、评论列表。 但是并不是所有的最新列表都能用list类型实现因为对于频繁更新的列表list类型的分页可能导致列表元素重复或漏掉举个例子当前列表里由表头到表尾依次有(EDCBA)五个元素每页获取3个元素用户第一次获取到(EDC)三个元素然后表头新增了一个元素F列表变成了(FEDCBA)此时用户取第二页拿到(CBA)元素C重复了。可以尾插头拿 即 左边插入从右边拿。 只有不需要分页(比如每次都只取列表的前5个元素)或者更新频率低(比如每天凌晨更新一次)的列表才适合用list类型实现。 对于需要分页并且会频繁更新的列表需用使用有序集合sorted set类型实现。 另外需要通过时间范围查找的最新列表list类型也实现不了也需要通过有序集合sorted set类型实现如以成交时间范围作为条件来查询的订单列表。之后在介绍有序集合sorted set类型的应用场景时会详细介绍sorted set类型如何实现最新列表。 那么问题来了,对于排行榜和最新列表两种应用场景,list类型能做到的sorted set类型都能做到,list类型做不到的sorted set类型也能做到,那为什么还要使用list类型去实现排行榜或最新列表呢直接用sorted set类型不是更好吗? 原因是sorted set类型占用的内存容量是list类型的数倍之多(之后会在容量章节详细介绍)对于列表数量不多的情况可以用sorted set类型来实现比如上文中举例的打擂金曲排行榜每天全国只有一份两种数据类型的内存容量差距可以忽略不计但是如果要实现某首歌曲的翻唱作品地区排行榜数百万的歌曲300多个地区会产生数量庞大的榜单或者数量更加庞大的朋友圈点赞列表就需要慎重地考虑容量的问题了。 底层数据结构压缩列表和双向链表 在版本3.2之前Redis 列表list使用两种数据结构作为底层实现 压缩列表ziplist双向链表linkedlist因为双向链表占用的内存比压缩列表要多 所以当创建新的列表键时 列表会优先考虑使用压缩列表 并且在有需要的时候 才从压缩列表实现转换到双向链表实现。 ziplist ziplist 是一个特殊的双向链表 特殊之处在于没有维护双向指针:prev next而是存储上一个 entry的长度和 当前entry的长度通过长度推算下一个元素在什么地方。 牺牲读取的性能获得高效的存储空间因为(简短字符串的情况)存储指针比存储entry长度 更费内存。这是典型的“时间换空间”。 ziplist使用局限性 字段、值比较小才会用ziplist。 压缩列表ziplist存储结构 ziplist使用连续的内存块每一个节点(entry)都是连续存储的 1.ziplist可以通过data header计算出当前entry的结束位置也就能得到下一个entry的起始位置正向遍历 2.ziplist可以通过length of previous entry计算出上一个entry的起始位置,反向遍历 压缩列表转化成双向链表条件 创建新列表时 redis 默认使用 redisencodingziplist 编码 当以下任意一个条件被满足时 列表会被转换成 redisencodinglinkedlist 编码 试图往列表新添加一个字符串值且这个字符串的长度超过 server.listmaxziplist_value (默认值为 64字节)。ziplist 包含的节点超过 server.listmaxziplist_entries (默认值为 512 )。 注意这两个条件是可以修改的在 redis.conf 中 list-max-ziplist-value 64 list-max-ziplist-entries 512 linkedlist 当链表entry数据超过512、或单个value 长度超过64字节底层就会转化成linkedlist编码 linkedlist是标准的双向链表Node节点包含prev和next指针可以进行双向遍历 还保存了 head 和 tail 两个指针因此对链表的表头和表尾进行插入的复杂度都为 (1) —— 这是高效实现 LPUSH 、 RPOP、 RPOPLPUSH 等命令的关键。