3.redis数据结构之List

这篇具有很好参考价值的文章主要介绍了3.redis数据结构之List。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

List-列表类型:L&R

列表类型:有序、可重复

Arraylist和linkedlist的区别

Arraylist是使用数组来存储数据,特点:查询快、增删慢

Linkedlist是使用双向链表存储数据,特点:增删快、查询慢,但是查询链表两端的数据也很快。

Redis的list是采用来链表来存储的,所以对于redis的list数据类型的操作,是操作list的两端数据来操作的。

命令

向列表左边增加元素:lpush key:val1 val2

127.0.0.1:6379>lpush list:1 1 2 3 (integer) 3

向列表右边增加元素:rpush key:val1 val2

127.0.0.1:6379>rpush 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 key&RPOP 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值的不同,该命令的执行方式会有所不同: 当count>0时, LREM会从列表左边开始删除。 当count<0时, LREM会从列表后边开始删除。 当count=0时, 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类型的分页可能导致列表元素重复或漏掉,举个例子,当前列表里由表头到表尾依次有(E,D,C,B,A)五个元素,每页获取3个元素,用户第一次获取到(E,D,C)三个元素,然后表头新增了一个元素F,列表变成了(F,E,D,C,B,A),此时用户取第二页拿到(C,B,A),元素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 等命令的关键。 文章来源地址https://www.toymoban.com/news/detail-668369.html

到了这里,关于3.redis数据结构之List的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • mysql数据库递归查询树形结构(适用场景:菜单多级分类,多级关联评论查询),用strea流把list转成树的方法详解

    层次关系: 现在的需求是把这个层级关系,在前端显示出来,后端的处理方法有两种: 1.直接把全部的数据从数据库中拿到,然后在java代码里面使用树形结构来进行解析,但是这种做法只能在数据量比较小的时候使用,然后数据量一大会造成内存溢出 2.在mysql中创建一个函数

    2024年02月05日
    浏览(28)
  • 数据结构之list类

    list是列表类。从list 类开始,我们就要接触独属于 Python 的数据类型了。Python 简单、易用,很大一部分原因就是它对基础数据类型的设计各具特色又相辅相成。 话不多说,让我们开始学习第一个 Python 数据类型一list。 1. list的赋值 输出结果 2. Python中list的知识点 list 类与str类

    2024年01月19日
    浏览(27)
  • day32 泛型 数据结构 List

     概述         JDK1.5同时推出了两个和集合相关的特性:增强for循环,泛型         泛型可以修饰泛型类中的属性,方法返回值,方法参数, 构造函数的参数 Java提供的泛型类/接口 Collection, List, Set,Iterator 等 自定义的泛型 public class Student H,W {} 自定义的泛型方法 public

    2024年02月09日
    浏览(28)
  • 数据结构编程题:Phone List

    Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers: 段落大意:给定一组电话号码,判断它们是否一致,即没有一个号码是另一个号码的前缀。假设电话目录列出了以下号码: Emergency 911 Alice 97 625 999

    2024年01月22日
    浏览(42)
  • 数据结构与算法 | 链表(Linked List)

    链表(Linked List)是一种线性数据结构,它由一系列节点(Node)组成,每个节点包含两部分:数据和指向下(上)一个节点的引用(或指针)。链表中的节点按照线性顺序连接在一起(相邻节点不需要存储在连续内存位置),不像数组一样存储在连续的内存位置。链表通常由

    2024年02月08日
    浏览(36)
  • 数据结构之List(双向链表)的实现

    方法名 参数 功能 返回 find const T val, int n, listNode * p 区间查找 从p往前数n个节点 指针或NULL const T val, listNode * p 区间查找 从p往前到首节点 const T val 查找 Size void 链表规模 size empty void 判空 bool first void 返回首节点 首节点指针 clear void 清空链表 void insertAsFirst const T val 作为首节

    2024年02月16日
    浏览(36)
  • 数据结构英文习题解析-第二章 链表List

    前言:最近快到FDS考试了,po重刷了一下学校的题目,自己整理了一些解析orz 因为po在自己找解析和学习的过程中非常痛苦,所以在此共享一下我的题目和自己写的解题思路,欢迎各位指出错误~全章节预计会陆续更新,可在专栏查看~ HW2 1. For a sequentially stored linear list of leng

    2024年04月11日
    浏览(41)
  • 【数据结构】 List与顺序表及接口的实现

    在集合框架中, List是一个接口,继承自Collection。 Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示: Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下: List 的官方文档 站在数据结构的角度来看, List就是一

    2024年02月12日
    浏览(30)
  • Map,List,Set 等集合以及底层数据结构

    集合类存放于java.util包中。集合类存放的都是对象的引用,而非对象本身。常见的集合主要有三种——Set(集)、List(列表)和Map(映射)。其中,List和Set 都 实现 了 Collection 接口,并且List和Set也是接口,而 Map 为独立接口 。常见的实现类如下: List 的实现类有:ArrayList、

    2024年02月09日
    浏览(37)
  • 浙大数据结构第二周之02-线性结构3 Reversing Linked List

    Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6. Input Specification: Each input file contains one test case. For each case, the first line

    2024年02月15日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包