Redis的五大数据类型介绍

news2024/11/16 11:59:31

33f69ec7e94b49a08c544c85ce7d7e88.jpg、简介

 

Redis的五大数据类型也称五大数据对象;前面介绍过6大数据结构,Redis并没有直接使用这些结构来实现键值对数据库,而是使用这些结构构建了一个对象系统redisObject;这个对象系统包含了五大数据对象,字符串对象(string)、列表对象(list)、哈希对象(hash)、集合(set)对象和有序集合对象(zset);而这五大对象的底层数据编码可以用命令OBJECT ENCODING来进行查看。

 

redisObject结构

 

复制代码

1 typedef struct redisObject {

2 // 类型

3 unsigned type:4;

4 // 编码

5 unsigned encoding:4;

6 // 指向底层实现数据结构的指针

7 void *ptr;

8 // ...

9 } robj;

复制代码

redis是以键值对存储数据的,所以对象又分为键对象和值对象,即存储一个key-value键值对会创建两个对象,键对象和值对象。

 

键对象总是一个字符串对象,而值对象可以是五大对象中的任意一种。

 

type属性存储的是对象的类型,也就是我们说的 string、list、hash、set、zset中的一种,可以使用命令 TYPE key 来查看。

encoding属性记录了队形所使用的编码,即这个对象底层使用哪种数据结构实现。

 

 

表中列出了底层编码常量及对应的OBJECT ENCODING 命令的输出,前三项都是字符串结构

 

我们在存入key-value键值对时并不会指定对象的encoding,而是Redis会根据不统的使用场景来为一个对象设置不同的编码,可以达到节约内存、加快访问速度等目的。

 

 

 

2、字符串对象(string)

字符串对象底层数据结构实现为简单动态字符串(SDS)和直接存储,但其编码方式可以是int、raw或者embstr,区别在于内存结构的不同。

 

(1)int编码

 

字符串保存的是整数值,并且这个正式可以用long类型来表示,那么其就会直接保存在redisObject的ptr属性里,并将编码设置为int,如图:

 

 

 

(2)raw编码

 

 字符串保存的大于32字节的字符串值,则使用简单动态字符串(SDS)结构,并将编码设置为raw,此时内存结构与SDS结构一致,内存分配次数为两次,创建redisObject对象和sdshdr结构,如图:

 

 

 

(3)embstr编码

 

 字符串保存的小于等于32字节的字符串值,使用的也是简单的动态字符串(SDS结构),但是内存结构做了优化,用于保存顿消的字符串;内存分配也只需要一次就可完成,分配一块连续的空间即可,如图:

 

 

 

 字符串对象总结:

 

在Redis中,存储long、double类型的浮点数是先转换为字符串再进行存储的。

raw与embstr编码效果是相同的,不同在于内存分配与释放,raw两次,embstr一次。

embstr内存块连续,能更好的利用缓存在来的优势

int编码和embstr编码如果做追加字符串等操作,满足条件下会被转换为raw编码;embstr编码的对象是只读的,一旦修改会先转码到raw。

3、列表对象(list)

列表对象的编码可以是ziplist和linkedlist之一。

 

(1) ziplist编码

 

ziplist编码的哈希随想底层实现是压缩列表,每个压缩里列表节点保存了一个列表元素。

 

 

 

(2)linkedlist编码

 

linkedlist编码底层采用双端链表实现,每个双端链表节点都保存了一个字符串对象,在每个字符串对象内保存了一个列表元素。

 

 

 

列表对象编码转换:

 

列表对象使用ziplist编码需要满足两个条件:一是所有字符串长度都小于64字节,二是元素数量小于512,不满足任意一个都会使用linkedlist编码。

两个条件的数字可以在Redis的配置文件中修改,list-max-ziplist-value选项和list-max-ziplist-entries选项。

图中StringObject就是上一节讲到的字符串对象,字符串对象是唯一个在五大对象中作为嵌套对象使用的。

 

 

4、哈希对象(hash)

哈希对象的编码可以是ziplist和hashtable之一。

 

(1)ziplist编码

 

ziplist编码的哈希对象底层实现是压缩列表,在ziplist编码的哈希对象中,key-value键值对是以紧密相连的方式放入压缩链表的,先把key放入表尾,再放入value;键值对总是向表尾添加。

 

 

 

(2)hashtable编码

 

hashtable编码的哈希对象底层实现是字典,哈希对象中的每个key-value对都使用一个字典键值对来保存。

 

字典键值对即是,字典的键和值都是字符串对象,字典的键保存key-value的key,字典的值保存key-value的value。

 

 

 

哈希对象编码转换:

 

哈希对象使用ziplist编码需要满足两个条件:一是所有键值对的键和值的字符串长度都小于64字节;二是键值对数量小于512个;不满足任意一个都使用hashtable编码。

以上两个条件可以在Reids配置文件中修改hash-max-ziplist-value选项和hash-max-ziplist-entries选项。

 

 

5、集合对象(set)

集合对象的编码可以是intset和hashtable之一。

 

(1)intset编码

 

intset编码的集合对象底层实现是整数集合,所有元素都保存在整数集合中。

 

 

 

(2)hashtable编码

 

hashtable编码的集合对象底层实现是字典,字典的每个键都是一个字符串对象,保存一个集合元素,不同的是字典的值都是NULL;可以参考java中的hashset结构。

 

 

 

集合对象编码转换:

 

集合对象使用intset编码需要满足两个条件:一是所有元素都是整数值;二是元素个数小于等于512个;不满足任意一条都将使用hashtable编码。

以上第二个条件可以在Redis配置文件中修改et-max-intset-entries选项。

 

 

 6、有序集合对象(zset)

有序集合的编码可以是ziplist和skiplist之一。

 

(1)ziplist编码 

 

ziplist编码的有序集合对象底层实现是压缩列表,其结构与哈希对象类似,不同的是两个紧密相连的压缩列表节点,第一个保存元素的成员,第二个保存元素的分值,而且分值小的靠近表头,大的靠近表尾。

 

 

 

(2)skiplist编码

 

skiplist编码的有序集合对象底层实现是跳跃表和字典两种;

 

每个跳跃表节点都保存一个集合元素,并按分值从小到大排列;节点的object属性保存了元素的成员,score属性保存分值;

 

字典的每个键值对保存一个集合元素,字典的键保存元素的成员,字典的值保存分值。

 

 

 

为何skiplist编码要同时使用跳跃表和字典实现?

 

跳跃表优点是有序,但是查询分值复杂度为O(logn);字典查询分值复杂度为O(1) ,但是无序,所以结合连个结构的有点进行实现。

虽然采用两个结构但是集合的元素成员和分值是共享的,两种结构通过指针指向同一地址,不会浪费内存。

有序集合编码转换:

 

有序集合对象使用ziplist编码需要满足两个条件:一是所有元素长度小于64字节;二是元素个数小于128个;不满足任意一条件将使用skiplist编码。

以上两个条件可以在Redis配置文件中修改zset-max-ziplist-entries选项和zset-max-ziplist-value选项。

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

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

相关文章

MFC第二十四天 使用GDI对象画笔和画刷来开发控件(分页控件选择态的算法分析、使用CToolTipCtrl开发动静态提示)

文章目录 GDI对象画笔和画刷来开发控件梯形边框的按钮控件CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp 矩形边框的三态按钮控件 CToolTipCtrl开发动静态提示CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp: 实现文件 矩形边框的三态按钮控件 CToolTipCtrl开发动…

linux服务器安装redis

一、安装下载 下载安装参考文章 下载安装包地址:https://download.redis.io/releases/ 亲测有效,但是启动的步骤有一些问题 安装完成!!! 二、启动 有三种启动方式 默认启动指定配置启动开机自启 说明&#xff1a…

CentOS下 Docker、Docker Compose 的安装教程

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 Docker Compose是用于定义…

【Lua学习笔记】Lua进阶——Table(4)继承,封装,多态

文章目录 封装继承多态 封装 // 定义基类 Object {}//由于表的特性,该句就相当于定义基类变量 Object.id 1//该句相当于定义方法,Object可以视为定义的对象,Test可以视为方法名 //我们知道Object是一个表,但是抽象地看&#xff…

为什么要有虚拟内存?

操作系统是通过内存分段和内存分页的方式管理虚拟内存地址和物理内存地址之间的关系 内存分段 程序是由若干个逻辑分段组成的,代码分段、数据分段、栈段、堆段组成,不同的段有不同的属性,所以就用分段的形式分离开。 分段机制下的虚拟内存…

【业务功能篇58】Springboot + Spring Security 权限管理 【下篇】

4.2.2.3 SpringSecurity工作流程分析 SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KjoRRost-1690534711077)(http…

使用Django自带的后台管理系统进行数据库管理的实例

Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能,可以让你快速创建一个管理界面,用于管理你的应用程序的数据模型。 使用Django后台管理系统,你可以轻松地进行以下操作: 数据库管理&…

详解机器学习中的熵、条件熵、相对熵和交叉熵

这个是讲的不错的链接 https://www.cnblogs.com/kyrieng/p/8694705.html 这个是交叉熵 https://blog.csdn.net/m0_57236802/article/details/129554878

《焊接点云处理》-角焊焊缝处理

角焊缝点云处理 前言一、代码二、实现步骤3、验证前言 针对T型板,识别效果如下所示 一、代码 主函数 #include "CGALRECONSTRUCT.h" #include "CGALREGIONPLANE.h" #include

设计利器,掌握CAD辅助命令的必备指南

CAD设计中的辅助命令是提高效率和确度的关键工具。掌握并正确运用CAD中的各种辅助命令对于设计师们来说至关重要。本文将为你详细介绍如何使用CAD中的辅助命令,从而帮助你在设计过程中更加高效地实现你的创意。、 大家有没有发现,当我们的直线命令移动到…

Rethinking the Image Fusion(PMGI)

1.摘要 本文提出了一种基于梯度和强度比例维护(PMGI)的快速统一图像融合网络,可以端到端实现各种图像融合任务,包括红外和可见图像融合、多曝光图像融合、医学图像融合、多焦点图像融合和全色增强。我们将图像融合问题统一为源图…

C++信号量与共享内存实现进程间通信

关于信号量和共享内存的相关知识可参考下面链接: 进程间通信方式介绍_夜雨听萧瑟的博客-CSDN博客 C 创建共享内存_c共享内存_夜雨听萧瑟的博客-CSDN博客 信号量SytemV与Posix信号量的介绍与用法_夜雨听萧瑟的博客-CSDN博客 直接上代码,代码如下&#…

蓝桥杯单片机第十二届国赛 真题+代码

iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础&#xff0c;根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求&#xff0c;进行代码调试和修改。 */ #include <STC1…

golang文件锁,目录锁,syscall包的使用

先说结论 1. golang提供了syscall包来实现文件/目录的加锁&#xff0c;解锁 2. syscall包属于文件锁&#xff0c;是比较底层的技术&#xff0c;并不能在所有操作系统上完全实现&#xff0c;linux上实现了&#xff0c;windows下面就没有 3. 加锁时调用syscall.Flock(fd&#…

安全学习DAY09_加密逆向,特征识别

算法逆向&加密算法分类&#xff0c;特征识别 文章目录 算法逆向&加密算法分类&#xff0c;特征识别算法概念&#xff0c;分类单向散列加密 - MD5对称加密 - AES非对称加密 - RSA 常见加密算法识别特征&#xff0c;解密特点MD5密文特点BASE64编码特点AES、DES特点RSA密文…

leaftjs实现全国温度降水气压风速等值面风场洋流效果

实现内容 数据爬取、地图marker聚合、鼠标移动显示pop&#xff0c;风场&#xff0c;洋流&#xff0c;温度等值面、降水等值面、气压等值面、风速等值面&#xff0c;洋流方向、洋流流速展示、风场方向、风场风速展示&#xff0c;后期扩展小时预报&#xff0c;分钟预报、7天预报…

Modbus RTU协议 + 调试工具 + java工具类

春风若有怜花意&#xff0c;可否容我再少年 Modbus RTU通信协议指令学习 Modbus RTU协议是一种紧凑的&#xff0c;采用二进制表示数据的方式&#xff0c;带有循环冗余校验的校验和。 读取指令格式 使用过程中03功能码比较常用&#xff0c;所以以03读取为例 读请求&#xff…

Java的代理模式

java有三种代理模式 静态代理 jdk动态代理 cglib实现动态代理 代理模式的定义&#xff1a; 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;而代理对象可以在客户端和目标对象之间起到中介的…

打包出现ProjectBuildingException异常原因之一

一次正常打包操作突然出现 原因是同事不小心在集合模块里面添加了重复的模块引入