当前位置: 首页 > 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在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分

http://www.mrgr.cn/news/33134.html

相关文章:

  • 每天五分钟玩转深度学习pytorch:L1正则化和L2正则化的应用
  • WPF入门教学九 样式与模板
  • Kubeadm安装k8s集群
  • [产品管理-32]:NPDP新产品开发 - 30 - 文化、团队与领导力 - 领导力与团队的可持续发展
  • 2024/9/21 数学20题
  • 电机学习-有感BLDC开环控制(六步换相)
  • l2p论文环境安装(2) 复刻源码低版本环境版
  • docker minio启动命令
  • 【TypeScript】 数据类型
  • 『功能项目』QFrameWork拾取道具UGUI【69】
  • 字符串函数(2)
  • 【yolo破损纸板-包装盒-快递袋缺陷检测】
  • 《机器人SLAM导航核心技术与实战》第1季:第9章_视觉SLAM系统
  • 学习IEC 62055付费系统标准
  • 新版ssh客户端无法连接旧版服务器sshd的方法
  • 【学习笔记】手写Tomcat 四
  • 《AI时代程序员核心竞争力提升指南》
  • C++ 构造函数最佳实践
  • AUTOSAR汽车电子嵌入式编程精讲300篇-基于CAN总线的气动控制
  • 【linux-Day4】linux的基本指令<下>