• list类型常用命令及其底层数据结构


    list类型命令

    lpush/rpush

    格式:LPUSH key value [value …] 或 RPUSH key value [value …]

    功能:将一个或多个值 value 插入到列表 key 的表头/表尾(表头在左表尾在右)

    说明:如果有多个 value 值,对于 lpush 来说,各个 value 会按从左到右的顺序依次插入到表头;对于 rpush 来说,各个 value 会按从左到右的顺序依次插入到表尾。如果 key不存在,一个空列表会被创建并执行操作。当 key 存在但不是列表类型时,返回一个错误。执行成功时返回列表的长度。

    llen

    格式:LLEN key

    功能:返回列表 key 的长度。

    说明:如果 key 不存在,则 key 被解释为一个空列表,返回 0 。如果 key 不是列表类型,返回一个错误。

    lindex

    格式:LINDEX key index

    功能:返回列表 key 中,下标为 index 的元素。列表从 0 开始计数。

    说明:如果 index 参数的值不在列表的区间范围内(out of range),返回 nil 。

    lset

    格式:LSET key index value

    功能:将列表 key 下标为 index 的元素的值设置为 value 。

    说明:当 index 参数超出范围,或对一个空列表(key 不存在)进行 LSET 时,返回一个错误。

    lrange

    格式:LRANGE key start stop

    功能:返回列表 key 中指定区间[start, stop]内的元素,即包含两个端点。

    说明:List 的下标从 0 开始,即以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。超出范围的下标值不会引起错误。如果 start 下标比列表的最大下标 还要大,那么 LRANGE 返回一个空列表。如果 stop 下标比最大下标还要大,Redis 将 stop 的值设置为最大下标。

    lpushx 与 rpushx

    格式:LPUSHX key value 或 RPUSHX key value

    功能:将值 value 插入到列表 key 的表头/表尾,当且仅当 key 存在并且是一个列表。

    说明:当 key 不存在时,命令什么也不做。若执行成功,则输出表的长度。

    linsert

    格式:LINSERT key BEFORE|AFTER pivot value

    功能:将值 value 插入到列表 key 当中,位于元素 pivot 之前或之后。

    说明:当 pivot 元素不存在于列表中时,不执行任何操作,返回-1;当 key 不存在时,key 被视为空列表,不执行任何操作,返回 0;如果 key 不是列表类型,返回一个错误;如果命令执行成功,返回插入操作完成之后,列表的长度。

    lpop / rpop

    格式:LPOP key [count] 或 RPOP key [count]

    功能:从列表 key 的表头/表尾移除 count 个元素,并返回移除的元素。count 默认值 1

    说明:当 key 不存在时,返回 nil

    blpop / brpop

    格式:BLPOP key [key …] timeout 或 BRPOP key [key …] timeout

    功能:BLPOP/BRPOP 是列表的阻塞式(blocking)弹出命令。它们是 LPOP/RPOP 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP/BRPOP 命令阻塞,直到等待 timeout 超时或发现可弹出元素为止。当给定多个 key 参数时,按参数 key的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。timeout 为阻塞时长,单位为秒,其值若为 0,则表示只要没有可弹出元素,则一直阻塞。

    说明:假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。反之,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。

    rpoplpush

    格式:RPOPLPUSH source destination

    功能:命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:

    • 将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。

    • 将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。如果 source 不存在,值 nil 被返回,并且不执行其他动作。如果 source 和 destination相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。

    brpoplpush

    格式:BRPOPLPUSH source destination timeout

    功能:BRPOPLPUSH 是 RPOPLPUSH 的阻塞版本,当给定列表 source 不为空时,BRPOPLPUSH 的表现和 RPOPLPUSH 一样。当列表 source 为空时, BRPOPLPUSH 命令将阻塞连接,直到等待超时,或有另一个客户端对 source 执行 LPUSH 或 RPUSH 命令为止。timeout 为阻塞时长,单位为秒,其值若为 0,则表示只要没有可弹出元素,则一直阻塞。

    说明:假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。

    lrem

    格式:LREM key count value

    功能:根据参数 count 的值,移除列表中与参数 value 相等的元素。count 的值可以

    是以下几种:

    • count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。

    • count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。

    • count = 0 : 移除表中所有与 value 相等的值。

    说明:返回被移除元素的数量。当 key 不存在时, LREM 命令返回 0 ,因为不存在

    的 key 被视作空表(empty list)

    ltrim

    格式:LTRIM key start stop

    功能:对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指

    定区间之内的元素都将被删除。

    说明:下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。当 key 不是列表类型时,返回一个错误。如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,或者 start > stop , LTRIM 返回一个空列表,因为 LTRIM 已经将整个列表清空。如果 stop 下标比 end 下标还要大,Redis 将 stop 的值设置为 end 。

    list的底层数据结构

    quickList

    ​ quickList,快速列表,quickList 本身是一个双向无循环链表,它的每一个节点都是一个zipList。

    ​ zipList 与 linkedList 都存在有明显不足,而 quickList 则对它们进行了改进:吸取了 zipList 和 linkedList 的优点,避开了它们的不足。(zipList每插入或者删除一个都会挪动大面积的entry,linkedList内存太分散容易产生内存碎片)

    ​ quickList 本质上是 zipList 和 linkedList 的混合体。其将 linkedList 按段切分,每一段使用 zipList 来紧凑存储若干真正的数据元素,多个 zipList 之间使用双向指针串接起来。当然,对于每个 zipList 中最多可存放多大容量的数据元素,在配置文件中通过 list-max-ziplist-size属性可以指定。

    ​ 由于 zipList 是有大小限制的,所以在 quickList 中插入一个元素在逻辑上相对就比较复杂一些。假设要插入的元素的大小为 insertBytes,而查找到的插入位置所在的 zipList 当前的大小为 zlBytes,那么具体可分为下面几种情况:

    • 情况一:当 insertBytes + zlBytes <= list-max-ziplist-size 时,直接插入到 zipList 中相应位置即可

    • 情况二:当 insertBytes + zlBytes > list-max-ziplist-size,且插入的位置位于该 zipList 的首部位置,此时需要查看该 zipList 的前一个 zipList 的大小 prev_zlBytes。

      • 若 insertBytes + prev_zlBytes<= list-max-ziplist-size 时,直接将元素插入到前一个zipList 的尾部位置即可
      • 若 insertBytes + prev_zlBytes> list-max-ziplist-size 时,直接将元素自己构建为一个新的 zipList,并连入 quickList 中
    • 情况三:当 insertBytes + zlBytes > list-max-ziplist-size,且插入的位置位于该 zipList 的尾部位置,此时需要查看该 zipList 的后一个 zipList 的大小 next_zlBytes。

      • 若 insertBytes + next_zlBytes<= list-max-ziplist-size 时,直接将元素插入到后一个zipList 的头部位置即可
      • 若 insertBytes + next_zlBytes> list-max-ziplist-size 时,直接将元素自己构建为一个新的 zipList,并连入 quickList 中
    • 情况四:当 insertBytes + zlBytes > list-max-ziplist-size,且插入的位置位于该 zipList 的中间位置,则将当前 zipList 分割为两个 zipList 连接入 quickList 中,然后将元素插入到分割后的前面 zipList 的尾部位置。

    注意:情况一是需要移动内部entry节点的,由于8k东西少所以效率不算太低。

    ​ 对于删除操作,只需要注意一点,在相应的 zipList 中删除元素后,该 zipList 中是否还有元素。如果没有其它元素了,则将该 zipList 删除,将其前后两个 zipList 相连接。

  • 相关阅读:
    ABB码垛机器人IRB260通讯板维修
    怎样使用Pyglet库给推箱子游戏画关卡地图
    手写数字识别-基于卷积神经网络
    Ubuntu Linux 24.04 C语言TCP/IP socket编程基础知识
    20221122非累加的m3u8的ts切片列表的补全步骤
    阿里一面:多线程顺序运行有多少种方法?
    高德地图开发(六)——计算距离
    Self -Supervised Learning
    智能制造之路—从0开始打造一套轻量级MOM平台
    【计算机组成原理】加减运算和溢出判断
  • 原文地址:https://blog.csdn.net/weixin_60208935/article/details/128206151