redis的zset的底层实现_Redis(三)--- Redis的五大数据类型的底层实现

1、简介

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

redisObject结构

1 typedef structredisObject {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选项。

7、总结

在Redis的五大数据对象中,string对象是唯一个可以被其他四种数据对象作为内嵌对象的;

列表(list)、哈希(hash)、集合(set)、有序集合(zset)底层实现都用到了压缩列表结构,并且使用压缩列表结构的条件都是在元素个数比较少、字节长度较短的情况下;

四种数据对象使用压缩列表的优点:

(1)节约内存,减少内存开销,Redis是内存型数据库,所以一定情况下减少内存开销是非常有必要的。

(2)减少内存碎片,压缩列表的内存块是连续的,并分配内存的次数一次即可。

(3)压缩列表的新增、删除、查找操作的平均时间复杂度是O(N),在N再一定的范围内,这个时间几乎是可以忽略的,并且N的上限值是可以配置的。

(4)四种数据对象都有两种编码结构,灵活性增加。

参考:

《Redis设计与实现》黄健宏著,网上对Redis的详解等

此博客为笔者使用redis很久之后,参考网络上各类文章总结性书写,原创手打,如有错误欢迎指正。

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

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

相关文章

科学计算机简单编程_是“计算机科学”还是“编程”?

科学计算机简单编程by Sam Corcos由Sam Corcos 是“计算机科学”还是“编程”? (Is It “Computer Science” or “Programming”?) 教育政策白皮书(提示:它们不是同一个东西) (An education policy white paper (hint: they’re not the same thing))…

[Matlab] 画图命令

matlab画图命令,不定时更新以便查找 set(gcf, color, [1 1 1]);     % 使图背景为白色 alpha(0.4);           %设置平面透明度 plot(Circle1,Circle2,k--,linewidth,1.25);  % k--设置线型  ‘linewidth’,1.25  设置线宽度为1.25 %线型   …

django入门记录 2

1. 创建一个app, python manage.py startapp appname 2. 设计model,在appname/目录下编辑好model 3. 检测model的修改,python manage.py makemigrations appname 4. 自动执行数据库迁移,并同步管理数据库结构, python…

spark sql 数据类型转换_SparkSql 数据类型转换

1、SparkSql数据类型 1.1数字类型 ByteType:代表一个字节的整数。范围是-128到127 ShortType:代表两个字节的整数。范围是-32768到32767 IntegerType:代表4个字节的整数。范围是-2147483648到2147483647 LongType:代表8个字节的整数。范围是-9223372036854775808到92233720…

【Python】 list dict str

list & dict & str 这三种类型是python中最常用的几种数据类型。他们都是序列的一种 ■  序列通用操作 1. 分片 s[a:b] 返回序列s中从s[a]到s[b-1]的片段。注意s[0:0]是空集而不是s[0] s[a:b:c]  加入第三个参数以设置取样步长。可以设置成负数来从右向左取样 2. 加…

终端terminal的颜色配置

PS1 color 终端terminal的颜色配置 PS1"\[\e[92;1m\][\u\e[90;5m\e[25m\[\e[91;4m\]Atlas\e[24m\[\e[1m\]\[\e[92;1m\] \W ]\\$\[\e[0m\]" Set CodeDescriptionExamplePreview1Bold/Bright echo -e "Normal \e[1mBold" 2Dim echo -e "Normal \e[2mDi…

速度与激情的Webpack

Also published in my tech blog也发布在我的技术博客中 This is a guide that is meant to help you ease your development workflow and save your time by using a bunch of awesome tools that you’ve read about on the internet (does React Hot Loader ring any bells…

java nio socket长连接_nio实现Socket长连接和心跳

前段时间用bio方式,也就是传统io实现了socket的长连接和心跳,总觉着服务端开启多线程管理socket连接的方式过于消耗资源,数据并发的情况下可能会影响到性能,因此就尝试使用nio改进原来的代码。然而改进的过程却不像我起初设想的那…

unity让对象作为参数_C#+Unity学习笔记:类与对象

参考文献蜜酒厅通讯社 游戏部 石中居士对象(object):有状态、行为和身份的东西。状态(state):表示物体特征的信息,可以用来跟踪对象的状态。属性(properties):因为编程人员需要把控对象的状态,所以要对其进行访问。通过…

Tomcat 报 The valid characters are defined in RFC 7230 and RFC 3986

问题 24-Mar-2017 23:43:21.300 INFO [http-apr-8001-exec-77] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. java.lang.IllegalAr…

Linux Kernel Oops异常分析

0.linux内核异常常用分析方法 异常地址是否在0附近,确认是否是空指针解引用问题异常地址是否在iomem映射区,确认是否是设备访问总线异常问题,如PCI异常导致的地址访问异常异常地址是否在stack附近,如果相邻&#xff0c…

Centos7.5 VMtools的安装与卸载

一、安装1、自带tools: 选择VMware工具栏 > 虚拟机 > 安装VMtools2、挂载光驱3、tar -zxvf VMwareTools-10.3.2-9925305.tar.gz(这里以tar文件为例)4、切换到目标目录,执行(一定要使用root权限执行)…

gitter 卸载_最佳Gitter渠道:开发人员工具

gitter 卸载by Gitter通过吉特 最佳Gitter渠道:开发人员工具 (Best Gitter channels: Developer Tools) Developer tools have become essential to any kind of serious software development, also in the open source setting. They can ease the daily develop…

java 过滤脚本_我写的得到天气的Java代码,其中有过滤脚本和过滤HTMLtag的函数。...

public class WeatherFilter{private String html;private String target"http://weather.news.sohu.com/query.php?city北京";public WeatherFilter()throws Exception{this(null);}public WeatherFilter(String targetIn)throws Exception{if(targetIn!null)this.…

【懒癌发作】收集各种懒癌发作时用程序写作业的程序

updata:20170621 好的,已经是准高一了,现在看起来太蠢了。。。 -------------------------------------------------------------------------------------- 要真正的运用,程序一定是要来解决实际问题的——比如作业(懒就直说&…

50欧姆线设计 高频pcb_硬件设计基础100问(三)

硬件基础知识问答今天依旧是节前知识储备哦,jacky大神整理的硬件基础知识很细致,第三弹学起来!01 1、晶体管基本放大电路有共射、共集、共基三种接法,请简述这三种基本放大电路的特点。共射:共射放大电路具有放大电流和…

如何正确实现 Java 中的 HashCode

相等 和 Hash Code 从一般角度来看,Equality 是不错的,但是 hash code 更则具技巧性。如果我们在 hash code上多下点功夫,我们就能了解到 hash code 就是用在细微处去提升性能的。 大部分的数据结构使用equals去检查是否他们包含一个元素。例…

一亿小目标成就_成就卓越的一种方式:自我选择

一亿小目标成就by Prosper Otemuyiwa通过Prosper Otemuyiwa 成就卓越的一种方式:自我选择 (One way to Greatness: Pick Yourself) I’ve heard many people say this: “I want to be great”, but most people only just have wild thoughts & imaginations …

java操作文件爱女_Java的IO操作---File类

目标1)掌握File类作用2)可以使用file类中方法对文件进行读写操作。File类唯一与文件有关的类。使用file类可进行创建或删除操作,要想使用File类,首先观察File类的构造方法。public File(String pathname);实例化File类的时候,必须设置好路径。…

openssl创建私有ca

openssl创建私有ca1.ssl大概内容PKI:公钥基础设施结构CA:证书权威机构,PKI的核心CRL:证书吊销列表,使用证书之前需要检测证书有效性证书存储格式常见的X509格式包含内容 公钥有效期限证书的合法拥有人证书该如何使用CA的信息CA签名…