当前位置: 首页 > news >正文

[Redis][List]详细讲解

目录

  • 0.前言
  • 1.常用命令
    • 1.LPUSH / RPUSH
    • 2.LPUSHX / RPUSHX
    • 3.LRANGE
    • 4.LPOP / RPOP
    • 5.LINDEX
    • 6.LINSERT
    • 7.LLEN
    • 8.LREM
    • 9.LTRIM
    • 10.LSET
  • 2.阻塞版本命令
    • 0.是什么?
    • 1.BLPOP / BRPOP
  • 3.内部编码(旧版本,仅供参考)
    • 1.ziplist(压缩链表)
    • 2.linkedlist(链表)
    • 3.quicklist(快速链表) -> (现行方案)
  • 4.使用场景
    • 1.消息队列
    • 2.分频道的消息队列
    • 3.微博 Timeline


0.前言

  • 列表类型是⽤来存储多个有序的字符串,相当于数组/顺序表

    • 内部实现类似于”双端队列“(deque)
  • 列表中的每个字符串称为元素(element),⼀个列表最多可以存储 2 32 − 1 2^{32} - 1 2321个元素

  • 在Redis中,可以对列表两端插⼊(push)和弹出(pop),还可以获取指定范围的元素列表、 获取指定索引下标的元素等
    请添加图片描述

    请添加图片描述

  • 列表是⼀种⽐较灵活的数据结构,它可以充当栈和队列的⻆⾊,在实际开发上有很多应⽤场景

  • 列表类型的特点

    • 列表中的元素是有序的:这意味着可以通过索引下标获取某个元素或者某个范围的元素列表
    • 区分获取和删除的区别rem是删除,会导致列表的长度改变,index是获取元素,列表长度不会变化
    • 列表中的元素是允许重复的,而hash这样的类型,field是不能重复的
      请添加图片描述

1.常用命令

1.LPUSH / RPUSH

  • 功能:将一个或者多个元素从左侧(头插) / 右侧(尾插)放入到list
    • 注意:是按照键入在命令中的顺序,从左向右将命令中的元素插入到list中的
      • 例如LPUSH key 1 2 3 4,那么最后list呈现的结果为:4 3 2 1
  • 语法LPUSH/RPUSH key element [element ...]
  • 返回值:插入后list的长度
  • 时间复杂度:只插入一个元素为 O ( 1 ) O(1) O(1),插入多个元素为 O ( N ) O(N) O(N),N为插入元素个数

2.LPUSHX / RPUSHX

  • 功能:在key存在时,将⼀个或者多个元素从左侧(头插) / 右侧(尾插)放⼊到list中,不存在,直接返回
  • 语法LPUSHX/RPUSHX key element [element ...]
  • 返回值:插入后list的长度
  • 时间复杂度:只插入一个元素为 O ( 1 ) O(1) O(1),插入多个元素为 O ( N ) O(N) O(N),N为插入元素个数

3.LRANGE

  • 功能:获取从startend区间的所有元素,左闭右闭,下标支持负数
  • 语法LRANGE key start stop
  • 返回值:指定区间的元素
  • 时间复杂度 O ( N ) O(N) O(N)
  • 注意:Redis会尽可能地获取到给定区间的元素,如果给定区间非法,比如超出下标,就会尽可能地获取到对应的内容
    • Redis对于下标越界地处理方式类似于Python的切片操作

4.LPOP / RPOP

  • 功能:从list左侧取出元素(头删) / 右侧取出元素(尾删)
  • 语法LPOP/RPOP key
  • 返回值:取出的元素或者nil
  • 时间复杂度 O ( 1 ) O(1) O(1)

5.LINDEX

  • 功能:获取从左数第index位置的元素
  • 语法LINDEX key index
  • 返回值:取出的元素或者nil
  • 时间复杂度 O ( N ) O(N) O(N)

6.LINSERT

  • 功能:在特定位置插入元素
  • 语法LINSERT key <BEFORE | AFTER> pivot element
  • 返回值:插入后的list长度
  • 时间复杂度 O ( N ) O(N) O(N),N表示列表的长度
  • 注意LINSERT进行插入的时候,要根据基准值,找到对应的位置,从左往右找,找到第一个符合基准值的位置即可

7.LLEN

  • 功能:获取list长度
  • 语法LLEN key
  • 返回值list的长度
  • 时间复杂度 O ( 1 ) O(1) O(1)

8.LREM

  • 功能:删除元素
  • 语法LREM key count element
    • count:要删除的个数
      • count > 0:从头向尾删
      • count < 0:从尾向头删
      • count = 0:删除全部元素
    • element:要删除的值
  • 返回值:删除元素的个数
  • 时间复杂度 O ( N + M ) O(N + M) O(N+M),N为list的长度,M为要删除元素的个数

9.LTRIM

  • 功能:保留[start, stop区间内的元素,区间外面的元素就直接被删除了
  • 语法LTRIM key start stop
  • 时间复杂度 O ( N ) O(N) O(N),N为要删除元素的个数

10.LSET

  • 功能:根据下标,修改元素
  • 语法LSET key index element
  • 时间复杂度 O ( N ) O(N) O(N)

2.阻塞版本命令

0.是什么?

  • blpopbrpoplpoprpop的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致,除了
    • 在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的
      • 但如果列表中没有元素,⾮阻塞版本会立即返回nil
      • 但阻塞版本会根据timeout,阻塞⼀段时间,期间Redis可以执⾏其他命令,但要求执 ⾏该命令的客⼾端会表现为阻塞状态
    • 命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元素,命令⽴即返回
    • 如果多个客⼾端同时对⼀个键执⾏pop,则最先执⾏命令的客⼾端会得到弹出的元素
  • 阻塞版本的blpop和非阻塞版本lpop的区别
    • 列表不为空时
      请添加图片描述

    • 列表为空时,且5秒内没有新元素加入
      请添加图片描述

    • 列表为空时,且5秒内有新元素加入
      请添加图片描述


1.BLPOP / BRPOP

  • 功能LPOP / RPOP的阻塞版本
  • 语法:`BLPOP/BRPOP key [key …] timeout
  • 返回值:取出的元素或者nil
  • 时间复杂度 O ( 1 ) O(1) O(1)

3.内部编码(旧版本,仅供参考)

1.ziplist(压缩链表)

  • 当列表的元素个数⼩于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的⻓度都⼩于list-max-ziplist-value配置(默认64字节)时,Redis会选⽤ziplist来作为列表的内部编码实现来减少内存消耗

2.linkedlist(链表)

  • 当列表类型⽆法满⾜ziplist的条件时,Redis会使⽤linkedlist作为列表的内部实现

3.quicklist(快速链表) -> (现行方案)

  • 相当于是链表和压缩列表的结合:整体还是一个链表,链表的每个节点,是一个压缩列表
  • 每个压缩列表,都不让它太大,同时再把多个压缩列表通过链式结构连起来

4.使用场景

1.消息队列

  • Redis可以使⽤lpush + brpop命令组合实现经典的阻塞式⽣产者-消费者模型队列, ⽣产者客⼾端使⽤lpush从列表左侧插⼊元素,多个消费者客⼾端使⽤brpop命令阻塞式地从队列中 "争抢"队⾸元素。通过多个客⼾端来保证消费的负载均衡和⾼可⽤性
    请添加图片描述

2.分频道的消息队列

  • Redis同样使⽤lpush + brpop命令,但**通过不同的键模拟频道的概念,不同的消费者可以通过brpop不同的键值,实现订阅不同频道的理念**
    请添加图片描述

3.微博 Timeline

  • 每个⽤⼾都有属于⾃⼰的Timeline(微博列表),现需要分⻚展⽰⽂章列表。此时可以考虑使⽤列表,因为列表不但是有序的,同时⽀持按照索引范围获取元素
  • 每篇微博使⽤哈希结构存储,例如微博中3个属性:title、timestamp、content
    hmset mblog:1 title xx timestamp 1476536196 content xxxxx
    ...
    hmset mblog:n title xx timestamp 1476536196 content xxxxx
    
  • 向⽤⼾Timeline添加微博,user::mblogs作为微博的键
    lpush user:1:mblogs mblog:1 mblog:3
    ...
    lpush user:k:mblogs mblog:9
    
  • 分⻚获取⽤⼾的Timeline,例如获取⽤⼾1的前10篇微博
    keylist = lrange user:1:mblogs 0 9
    for key in keylist
    {hgetall key
    }
    
  • 此⽅案在实际中可能存在两个问题
    • 1+n问题:如果每次分⻚获取的微博个数较多,需要执⾏多次hgetall操作,此时可以考虑使⽤pipeline(流⽔线)模式批量提交命令,或者微博不采⽤哈希类型,⽽是使⽤序列化的字符串类型,使⽤mget获取
    • 分裂获取⽂章时,lrange在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Elasticsearch 应用实战:从基础到高级实践
  • Radware 报告 Web DDoS 攻击活动
  • 图书管理系统小程序的设计
  • 【autoware】编译时候出现“没有那个文件或目录 20 | #include <pcl/point_types.h>“错误
  • ChatGPT 4o 使用指南 (9月更新)
  • WebServer:buffer
  • 某省公共资源交易电子平台爬虫逆向
  • Spring Mybatis PageHelper分页插件 总结
  • 【JVM原理】运行时数据区(内存结构)
  • Open3D 利用点云的曲率密度提取特征点【2024最新版】
  • Linux1-ls,cd,pwd
  • Qt 模型视图(二):模型类QAbstractItemModel
  • 【自动驾驶】决策规划算法(一)决策规划仿真平台搭建 | Matlab + Prescan + Carsim 联合仿真基本操作
  • 信息安全工程师(8)网络新安全目标与功能
  • Python 如何调用讯飞星火大模型API
  • CentOS从零开始部署Nodejs项目
  • express如何解决request entity too large问题
  • JavaScript的使用你知道几种?(上)
  • leetcode386. Lexicographical Numbers
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Python学习之路13-记分
  • 聊聊flink的TableFactory
  • 少走弯路,给Java 1~5 年程序员的建议
  • 微信支付JSAPI,实测!终极方案
  • 正则学习笔记
  • 通过调用文摘列表API获取文摘
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (pojstep1.1.2)2654(直叙式模拟)
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (论文阅读11/100)Fast R-CNN
  • (南京观海微电子)——I3C协议介绍
  • (全注解开发)学习Spring-MVC的第三天
  • (十六)一篇文章学会Java的常用API
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)关于pipe()的详细解析
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .axf 转化 .bin文件 的方法
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .naturalWidth 和naturalHeight属性,
  • .NET Framework杂记
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .net 简单实现MD5
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】
  • .NET单元测试
  • /var/lib/dpkg/lock 锁定问题
  • @GlobalLock注解作用与原理解析
  • @ModelAttribute使用详解
  • @RequestBody的使用
  • [17]JAVAEE-HTTP协议
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Android]如何调试Native memory crash issue