Redis中的List

List类型定义

List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。

列表的最大长度为 $2^{32} - 1$,也即每个列表支持超过 40 亿个元素。

特点与LinkedList一致

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般

常见命令

  • 获取元素
    • LINDEX KEY_NAME INDEX_POSITION :通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素
  • 插入元素
    • LPUSH KEY_NAME VALUE1.. VALUEN :将一个或多个值插入到列表头部。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误。
    • LPUSHX KEY_NAME VALUE1.. VALUEN :将一个值插入到已存在的列表头部,列表不存在时操作无效。
    • LINSERT key BEFORE|AFTER pivot value :将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
    • RPUSH KEY_NAME VALUE1..VALUEN :将一个或多个值插入到列表的尾部(最右边)
    • RPUSHX KEY_NAME VALUE1..VALUEN :将一个值插入到已存在的列表尾部(最右边)。如果列表不存在,操作无效
    • BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT :Redis Brpoplpush 命令从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
  • 删除元素
    • BLPOP LIST1 LIST2 .. LISTN TIMEOUT :移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
      • 如果列表为空,返回一个 nil 。 否则,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。
    • BRPOP LIST1 LIST2 .. LISTN TIMEOUT :移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
      • 假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。 反之,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。
    • Lpop KEY_NAME :移除并返回列表的第一个元素
    • RPOP KEY_NAME :用于移除列表的最后一个元素,返回值为移除的元素

底层实现原理

List 类型的底层数据结构是由 双向链表或压缩列表 实现的:

  • 如果列表的元素个数小于 512 个(默认值,可由 list-max-ziplist-entries 配置),列表每个元素的值都小于 64 字节(默认值,可由 list-max-ziplist-value 配置),Redis 会使用 压缩列表(ziplist) 作为 List 类型的底层数据结构;
  • 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构

在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表

提示

Ziplist:压缩列表是 由连续内存块组成的顺序型数据结构 ,有点类似于数组

  • 优点:简单、紧凑、连续存储,适用于小数据量场景
  • 缺点:压缩列表新增某个元素或修改某个元素时,如果空间不不够,压缩列表占用的内存空间就需要重新分配。而当新插入的元素较大时,可能会导致后续元素的占用空间都发生变化,从而引起连锁更新问题,导致每个元素的空间都要重新分配,造成访问压缩列表性能的下降。

Quicklist

  • 通过将链表和 Ziplist 结合,既实现了链表的灵活操作,又能节省内存
  • Quicklist 是为了替代纯链表而设计的,适用于需要频繁对列表进行插入、删除、查找等操作的场景,并且数据量可能较大。它在存储多个元素时,既保留了链表的灵活性,又具备压缩列表的内存优势。
  • Quicklist 由 list 和 ziplist 结合而成,它是一个由 ziplist 充当节点的双向链表。

应用场景

简单消息队列

  • 消息保序性:使用 LPUSH + RPOPimg
    • 生产者使用 LPUSH key value[value...] 将消息插入到队列的头部,如果 key 不存在则会创建一个空的队列再插入消息。
    • 消费者使用 RPOP key 依次读取队列的消息,先进先出。
  • 消息重复性:自行为每个消息生成一个全局唯一ID
  • 消息可靠性:让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存
그 경기 끝나고 좀 멍하기 있었는데 여러분 이제 살면서 여러가
使用 Hugo 构建
主题 StackJimmy 设计