List【Redis对象篇】

🏆 作者简介:席万里
⚡ 个人网站:

文章目录

  • LIst
    • 1.简介
    • 2.使用场景
    • 3.常用操作
      • 1.写操作
      • 2.读操作
    • 4.底层实现
    • 5.压缩列表的优化
      • 1.ZIPLIST结构
      • 2.ziplist更新数据
      • 3.LISTPACK优化
    • 6.总结(重点)

LIst

1.简介

Redis List是一组连接起来的字符串集合。

List最大的元素个数是2的32次方-1,新版本4.0之后是64次方-1。

2.使用场景

List作为一个列表存储,属于比较底层的数据结构,比如存储一批任务数据、存储一批消息等。

3.常用操作

  • 创建:LPUSH、RPUSH
  • 查询:LLEN、LRANGE
  • 更新:LPUSH、RPUSH、LPOP、RPOP、LREN
  • 删除:DEL、UNLINK

1.写操作

1、LPUSH从左侧插入,RPSH从右侧插入

在这里插入图片描述
在这里插入图片描述

2、LPOP移出并获取列表的第一个元素;RPOP移出并获取列表最后一个元素

在这里插入图片描述

3、LREN key count value,移出值等于value的元素,当count=0,则移出素有等于value的元素,当count>0,则从左到右移出count个,当count<0,则从右到左移出count个。返回被移除元素的数量。

在这里插入图片描述

4、DEL和UNLINK,DEL是同步删除命令,UNLINK是异步删除命令不会阻塞客户端。

2.读操作

1、LLEN,查看list的长度

2、LRANGE,查看从start到stop的元素

在这里插入图片描述

4.底层实现

3.2版本之前,List对象有两种编码方式,ZIPLIST和LINKEDLIST。

ZIPLIST使用条件:

  1. 列表对象保存的所有字符串对象长度都小于64字节。
  2. 列表对象元素个数少于512个。

在这里插入图片描述

LinkedList:

在这里插入图片描述

ZIPLIST和LInkedList相比,ZIPLIST内存更加紧凑,所以只有在列表个数或节点数据比较大的时候,才会使用到LINKEDLIST编码。

所以,ZIPLIST是为了在数据较少时节约内存,LInkedList是为了数据多时提高更新效率,而ZIPLIST数据稍多时会导致很多内存复制。

后来,引入了QUICKLIST,其实就是ZIPLIST和LInkedLIST的结合体。

在这里插入图片描述

原来LInkedList是单个节点,只能存一个数据,现在单个节点存的是一个ZIPLIST,即多个数据。

5.压缩列表的优化

平常说的压缩列表一般是指ZIPLIST,一种是LISTPACK 5.0引入的,直到7.0完全替代了ZIPLIST。

1.ZIPLIST结构

在这里插入图片描述

  • zlbytes:占用4个字节,记录了整个ziplist占用的总字节数。
  • zltail:占用4个字节,指向最后一个entry偏移量,用于快速定位最后一个entry。
  • zllen:占用2字节,记录entry总数。
  • entry:列表元素。
  • zlend:ziplist结束标志,占用1字节,值等于255。

ziplist节点结构

<prevlen> <encoding> <entry-data>

prevlen:表示上一个节点的数据长度。如果前一节点的长度,也就是entry的大小 小于254字节,那么prevlen需要用1字节长的空间来保存这个长度值,255是特殊字符,被zlend占用了。

encoding:编码类型,包含了一个entry的长度信息,可用于正向遍历。

entry-data:实际的数据。

2.ziplist更新数据

更新操作可能带来连锁更新。连锁更新是指这个后移,发生了不止一次,而是多次。

什么是连锁更新?

比如增加一个头部新节点,后面依赖它的节点,需要prevlen记录它的大小,原本只用1字节记录,因为更新可能膨胀为5字节,然后这个entry的大小就也膨胀了。所以,当这个新数据插入导致的后移完成之后,还需要逐步迭代更新。

在这里插入图片描述

3.LISTPACK优化

ziplist需要支持LIST,LIST是双端访问的结构,所以需要能从后向前遍历。

<prevlen> <encoding> <entry-data>

其中,prevlen就表示上一个节点的数据长度,通过这个字段可以定位上一个节点的数据。

那么,我们可不可以改为不记录这个prevlen,但是又能找到上一个节点的起始位置的办法?

<encoding-type> <element-data> <element-tot-len>

encoding-type:是编码类型;element-datt:是数据内容;element-tot-len:存储整个节点除它自身的长度。

要找到上一个节点的秘密就需要element-tot-len

element-tot-len所占用的每个字节的第一个bit用于标识是否结束。0是结束,1是继续,剩下7个bit来存储数据大小。

当我们需要找到当前元素的上一个元素时,我们可以从后向前依次查找每个字节,找到上一个Entry的element-tot-len字段的结束标识。

6.总结(重点)

1、List对象底层编码方式是什么?

3.2版本之前,List底层的编码是ziplist和LInkedlist,当ziplist的节点数量或单个节点大小超过一定阈值时,就会转换成LINKLIST。在3.2版本,结合ziplist和linklist实现了quicklist作为list的新底层编码,而在更新的版本,ziplist优化成了listpack。

2、ziplist怎么压缩数据的?

ziplist采用紧凑的内存结构,节点之间的内存空间都是连续的。ziplist的结构大致可以分为三部分,结构头、数据部分、结尾标志;结构头包含了ziplist总字节大小、ziplist节点个数、ziplist最后一个节点的偏移量;数据部分有N个节点组成,单个节点包含节点编码类型,上一个节点的长度,节点实际数据。

3、ziplist下list可以从后向前遍历吗?

对于ziplist中的每一个节点,都记录了前一个节点的长度,我们可以用当前遍历节点的首地址减去这个长度,就能找到上一个节点的首地址。

4、ziplist的不足

当ziplist的元素个数变得很多之后,查找效率就会下降;而且因为ziplist内存是连续的,当其中一个节点需要更新,或者新增节点时,就需要重新分配内存;再者因为ziplist每一个节点记录了前一个节点的长度,当其中一个节点的长度发生变化时,会导致后面的节点都需要进行更新,引发连锁更新问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/64052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP8 动态属性被弃用兼容方案

PHP 类中可以动态设置和获取没有声明过的类属性。这些属性不遵循具体的规则&#xff0c;并且需要使用 __get() 和 __set() 魔术方法对动态属性如何读写进行有效控制。 class User {private int $uid; }$user new User(); $user->name Foo; 上述代码中&#xff0c;User 类…

专业125+总分400+南京理工大学818考研经验南理工电子信息与通信工程,真题,大纲,参考书。

考研成功上岸&#xff0c;苦尽甘来&#xff0c;专业818信号系统与数字电路125&#xff0c;总分400&#xff0c;被南理工录取&#xff0c;从最早信心满满&#xff0c;到中期犹豫不决&#xff0c;到后期破釜沉舟&#xff0c;一路颠颠簸簸&#xff0c;总算坚持过来了&#xff0c;群…

测试脚本并发多进程:pytest-xdist用法

参考&#xff1a;https://www.cnblogs.com/poloyy/p/12694861.html pytest-xdist详解&#xff1a; https://www.cnblogs.com/poloyy/p/14708825.html 总 https://www.cnblogs.com/poloyy/category/1690628.html

ruoyi Cannot find module ‘@/views/system/user/index‘

Cannot find module /views/system/user/index 删除node_module 后打包成功

mall-admin-web开源项目搭建教程(图文)

本章教程,介绍如何在本地部署运行mall-admin-web这个开源项目。 开源地址:https://gitee.com/macrozheng/mall-admin-web mall-admin-web是一个电商后台管理系统的前端项目,基于Vue+Element实现。主要包括商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计…

Dockerfile制作相关命令

一、常用命令 1. FROM 指令指定基础镜像 FROM <image>:<tag> 如 FROM ubuntu:20.04image: 基础镜像名称。 tag: 可选&#xff0c;镜像标签&#xff0c;默认为 latest。 如 2. RUN 用于在构建镜像时执行命令。可以用于安装软件包或配置文件等。 RUN <command&g…

【计算机视觉】边缘检测

图像的边缘简单来说就是图像中灰度不连续的地方。 1.图像梯度 图像梯度是指图像像素灰度值在某个方向上的变化&#xff1b;图像梯度是图像的一阶导数&#xff0c;实际计算时可以使用差分来近似。 1.1 什么是图像梯度&#xff1f; 图像梯度是一种数学工具&#xff0c;用于描…

@JsonNaming实现入参接口参数下划线驼峰自动转换

JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) 是用于 Jackson 库中的一个注解&#xff0c;作用是改变 Java 对象的字段命名策略&#xff0c;特别是在序列化和反序列化时。这可以帮助 Java 对象中的字段名从驼峰命名法&#xff08;CamelCase&#xff09;转换为蛇…

Microsemi Libero SoC免费许可证申请指南(Microchip官网2024最新方法)

点击如下链接&#xff1a; https://www.microchip.com/en-us/products/fpgas-and-plds/fpga-and-soc-design-tools/fpga/licensing 点击右侧&#xff0c;请求免费的License 如果提示登录&#xff0c;请先登录Microchip账号。 点击Request Free License。 选项一年免费的Li…

docker容器内部启动jupyter notebook但是宿主机无法访问的解决方法

目录 1.问题2.解决方法 1.问题 在docker容器内启动了jupyter notebook&#xff0c;在宿主机内用如下的url无法访问 http://localhost:8888 http://127.0.0.1:8888 启动方法&#xff1a; jupyter notebook 2.解决方法 启动方法加上选项[ --ip‘*’]或者[–ip‘0.0.0.0’] 即启…

[C++]类的继承

一、什么是继承 1.定义&#xff1a; 在 C 中&#xff0c;继承是一种机制&#xff0c;允许一个类&#xff08;派生类&#xff09;继承另一个类&#xff08;基类&#xff09;的成员&#xff08;数据和函数&#xff09;。继承使得派生类能够直接访问基类的公有和保护成员&#xf…

vue前端获取电脑本机的mac和ip地址

vue 前端 使用 node 里的 os 模块,来获取主机mac和IP地址 需要注意的是这篇教程只能获取本地的&#xff0c;打包到服务器上也是服务器的。需要获取不同使用者的客户端mac&#xff0c;看我这篇。获取客户端不同的mac地址 一、根目录创建 getNetworkInfo.js 脚本文件 const os …

harbor镜像仓库搭建

Harbor简介 Harbor的发展背景和现状 Harbor项目起始于2014年左右,当时正值容器技术和微服务架构迅速崛起的时期。随着越来越多的企业开始采用容器化部署应用,对于私有镜像管理的需求也日益增长。传统的解决方案要么缺乏必要的企业级特性(如访问控制、安全性和可扩展性),…

01-51单片机硬件基础

开发板介绍 学校授课用的是普中科技的EM3.V2.2开发板&#xff0c;没什么好说的&#xff0c;记着去淘宝上找原理图&#xff0c;别迷信课本。 网上有卖51最小系统板的&#xff0c;比开发板便宜&#xff0c;也有下载模块&#xff0c;可以自己搭建外围电路。 还可以自己在protue…

方法引用和lambda表达式的奥妙

方法引用替代Lambda表达式 什么情况可以使用方法引用替代lambda表达式&#xff1f; 下面代码中两处使用了lambda表达式&#xff0c;一个是filter内&#xff0c;一个是forEach内。其中&#xff0c;forEach内的lambda表达式可以被方法引用替代&#xff0c;但是filter内的lambda…

Android通过okhttp下载文件(本文案例 下载mp4到本地,并更新到相册)

使用步骤分为两步 第一步导入 okhttp3 依赖 第二步调用本文提供的 utils 第一步这里不做说明了&#xff0c;直接提供第二步复制即用 DownloadUtil 中 download 为下载文件 参数说明 这里主要看你把 destFileName 下载文件名称定义为什么后缀&#xff0c;比如我定义为 .mp4 下…

What is load balancing? 什么是负载均衡?

原文链接 What Is Load Balancing? | IBM 什么是负载均衡&#xff1f; 在多台服务器之间高效的分配网络流量的过程&#xff0c;以优化应用程序的可用性&#xff0c;同时确保积极的用户体验。 电商网站依赖负载均衡&#xff08;load balancing&#xff09;来确保web应用能够无…

dex2oat 提升启动速度

用途 build阶段可以将apk中dex生成oat文件&#xff08;odex&#xff09;&#xff0c;dex2oat 源码目录/system/bin/dex2oat 4种编译模式&#xff1a; verify&#xff1a;只运行 DEX 代码验证quicken&#xff1a;运行 DEX 代码验证&#xff0c;并优化一些 DEX 指令&#xff0c…

JavaScript 原型对象与原型链的魔法与艺术

在JavaScript的世界里&#xff0c;原型对象和原型链是两个非常重要的概念。它们不仅帮助我们理解对象的创建过程&#xff0c;还为我们提供了一种高效的方式来管理共享的属性和方法。本文将深入探讨JavaScript中的原型对象和原型链&#xff0c;包括它们的定义、工作原理以及在实…

力扣题目 - 3264.K 次乘运算后的最终数组I

题目 还需要你前往力扣官网查看详细的题目要求 地址 1.给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。2.你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a;找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最…