Redis(三)--- Redis的五大数据类型的底层实现
1、简介
Redis的五大数据类型也称五大数据对象;前面介绍过6大数据结构,Redis并没有直接使用这些结构来实现键值对数据库,而是使用这些结构构建了一个对象系统redisObject;这个对象系统包含了五大数据对象,字符串对象(string)、列表对象(list)、哈希对象(hash)、集合(set)对象和有序集合对象(zset);而这五大对象的底层数据编码可以用命令OBJECT ENCODING来进行查看。
redisObject结构
 typedef struct redisObject {
     // 类型
     unsigned type:;
     // 编码
     unsigned encoding:;
     // 指向底层实现数据结构的指针
     void *ptr;
     // ...
 } 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很久之后,参考网络上各类文章总结性书写,原创手打,如有错误欢迎指正。
Redis(三)--- Redis的五大数据类型的底层实现的更多相关文章
- Linux07 /redis的配置、五大数据类型、发布订阅、持久化、主从复制、哨兵配置、集群搭建
		Linux07 /redis的配置.五大数据类型.发布订阅.持久化.主从复制.哨兵配置.集群搭建 目录 Linux07 /redis的配置.五大数据类型.发布订阅.持久化.主从复制.哨兵配置.集群搭建 ... 
- Redis数据库 01概述| 五大数据类型
		1.NoSQL数据库简介 解决应用服务器的CPU和内存压力:解决数据库服务的IO压力: ----->>> ① session存在缓存数据库(完全在内存里),速度快且数据结构简单: 打 ... 
- 10、Redis三种特殊的数据类型
		一.Geospatail地理位置 1.Geospatail的应用 朋友的位置,附近的人,打车距离 2.相关命令 1.geoadd:增加某个地理位置的坐标(可批量添加). 语法: GEOADD key ... 
- redis(三)-----redis基本数据类型
		Redis的全称是REmote Dictionary Server,它主要提供了5种数据结构:字符串.哈希.列表.集合.有序集合,同时在字符串的基础之上演变 出了位图(Bitmaps)和HyperLo ... 
- redis(三)redis+Keepalived主从热备秒级切换
		一 简介 安装使用centos 5.10 Master 192.168.235.135 Slave 192.168.235.152 Vip 192.168.235.200 编译环境 yum -y in ... 
- Redis详解(三)------ redis的五大数据类型详细用法
		我们说 Redis 相对于 Memcache 等其他的缓存产品,有一个比较明显的优势就是 Redis 不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据 ... 
- Redis 详解 (三) redis的五大数据类型详细用法
		目录 1.string 数据类型 2.hash 数据类型 3.list 数据类型 4.set 数据类型 5.zset 数据类型 6.系统相关命令 7.key 相关命令 我们说 Redis 相对于 Me ... 
- Redis详解(五)------ redis的五大数据类型实现原理
		前面两篇博客,第一篇介绍了五大数据类型的基本用法,第二篇介绍了Redis底层的六种数据结构.在Redis中,并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这些对 ... 
- 3 Redis 的常用五大数据类型
		2016-12-21 14:54:20 该系列文章链接NoSQL 数据库简介Redis的安装及及一些杂项基础知识Redis 的常用五大数据类型(key,string,hash,list,set,zse ... 
随机推荐
- 当程序调用dll时获取dll路径,DLL中获取自身的句柄
			当程序调用dll时,获取dll路径的方法: HMODULE hMod = GetModuleHandle(_T("axload.dll")); if (hMod != NULL) ... 
- 深入理解JVM(一)虚拟机内存
			一 .前言 JVM是什么,我想诸位肯定都清楚. 好吧,我还是简答说一下JVM即Java虚拟机(够简单吧 233333). 虽然说,所有抛开操作系统,讲虚拟机的内容,都是耍流氓.但是,贫僧不修善果,就爱 ... 
- 再说Java集合,subList之于ArrayList
			上一章说了很多ArrayList相关的内容,但还有一块儿内容没说到,那就是subList方法.先看一段代码 public static void testSubList() { List<Str ... 
- ThreadLocal使用原理、注意问题、使用场景
			想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码 ... 
- Python|网页转PDF,PDF转图片爬取校园课表~
			import pdfkit import requests from bs4 import BeautifulSoup from PIL import Image from pdf2image imp ... 
- EditPlus 格式化HTML JS  CSS
			首先你得安装一个EditPlus,然后下载你想格式化的xxxformatter.js文件,也就是网上说的EDTOOLS 1.在你的工具里边找到-->配置自定义工具 具体做法如下: 第5步 命令: ... 
- 【多处摘抄】Tomcat监视与调优
			文章摘抄大量内容,已附上摘抄地址,未找到最初博文作者,在此对原作者表述感谢: 最近调整了公司的Web容器,然后把项目转移到了idea,并且重新分了包,我以前很多重复的东西整合了一下,但是最近线下 ... 
- PHP中var_dump、&&和GLOBALS的爱恨纠缠
			var_dump函数:用来打印显示一个变量的内容与结构: &&:定义一个可变变量.php中,在定义变量时,需要在前面加上一个“&”符号,当加上两个“&&”符号时 ... 
- java 获取客户端的ip地址
			import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHo ... 
- Git 安装教程(2.21.0)
			获取安装包地址 1.官网(较慢):https://git-scm.com/downloads 2.下载链接:http://down-ww3.newasp.net/pcdown/soft/soft1/g ... 
