文档章节

面试:原来Redis的五种数据类型底层结构是这样的

c
 ccww_
发布于 10/22 23:26
字数 1788
阅读 29
收藏 1

关注我,可以获取最新知识、经典面试题以及微服务技术分享

  在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统,而且自定义的对象系统有很多好处。

通过对以下的Redis对象系统的学习,可以了解Redis设计原理以及初衷,为了我们在使用Redis的时候,更加能够理解到其原理和定位问题。

Redis 对象

Redis基于上述的数据结构自定义一个Object 系统,Object结构:

redisObject结构:
	 typedef struct redisObject{
	//类型
	unsigned type:4;
	//编码
	unsigned encoding:4;
	//指向底层实现数据结构的指针
	void *ptr;
	….. 
} 

Object 系统包含五种Object:

  • String:字符串对象
  • List:列表对象
  • Hash:哈希对象
  • Set:集合对象
  • ZSet:有序集合

Redis使用对象来表示数据库中的键和值,即每新建一个键值对,至少创建有两个对象,而且使用对象的具有以下好处: 1. redis可以在执行命令前会根据对象的类型判断一个对象是否可以执行给定的命令 2. 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象的不同场景夏的使用效率 3. 对象系统还可以基于引用计数计数的内存回收机制,自动释放对象所占用的内存,或者还可以让多个数据库键共享同一个对象来节约内存。 4. redis对象带有访问时间记录信息,使用该信息可以进行优化空转时长较大的key,进行删除!

<br> 对象的ptr指针指向对象的底层现实数据结构,而这些数据结构由对象的encoding属性决定,对应关系:

编码常量 编码对应的底层数据结构
REDIS_ENCODING_INT long类型的整数
REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串
REDIS_ENCODING_RAW 简单动态字符串
REDIS_ENCODING_HT 字典
REDIS_ENCODING_LINKEDLIST 双向链表
REDIS_ENCODING_ZIPLIST 压缩列表
REDIS_ENCODING_INTSET 整数集合
REDIS_ENCODING_SKIPLIST 跳跃表和字典

<br> 每种Object对象至少有两种不同的编码,对应关系:

类型 编码 对象
String int 整数值实现
String embstr sds实现 <=39 字节
String raw sds实现 > 39字节
List ziplist 压缩列表实现
List linkedlist 双端链表实现
Set intset 整数集合使用
Set hashtable 字典实现
Hash ziplist 压缩列表实现
Hash hashtable 字典使用
Sorted set ziplist 压缩列表实现
Sorted set skiplist 跳跃表和字典

<br> ## String 对象

字符串对象编码可以int 、raw或者embstr,如果保存的值为整数值且这个值可以用long类型表示,使用int编码,其他编码类似。

比如:int编码的String Object

redis> set number 520 
 ok
 redis> OBJECT ENCODING number 
"int"

String Object结构:

file

String 对象之间的编码转换

int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。

比如:对int编码的字符串对象进行append命令时,就会使得原来是int变为raw编码字符串

<br> ## List对象

list对象可以为ziplist或者为linkedlist,对应底层实现ziplist为压缩列表,linkedlist为双向列表。

Redis>RPUSH numbers “Ccww” 520 1

用ziplist编码的List对象结构:
file

用linkedlist编码的List对象结构:

file

List对象的编码转换:

当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码: 1. list对象保存的所有字符串元素的长度都小于64字节 2. list对象保存的元素数量小于512个, 不能满足这两个条件的list对象需要使用linkedlist编码。

Hash对象

Hash对象的编码可以是ziplist或者hashtable 其中,ziplist底层使用压缩列表实现:

  • 保存同一键值对的两个节点紧靠相邻,键key在前,值vaule在后
  • 先保存的键值对在压缩列表的表头方向,后来在表尾方向

hashtable底层使用字典实现,Hash对象种的每个键值对都使用一个字典键值对保存:

  • 字典的键为字符串对象,保存键key
  • 字典的值也为字符串对象,保存键值对的值

比如:HSET命令

redis>HSET author name  "Ccww"
(integer)

redis>HSET author age  18
(integer)

redis>HSET author sex  "male"
(integer)

ziplist的底层结构:

file

hashtable底层结构:

file

Hash对象的编码转换:

当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码: 1. list对象保存的所有字符串元素的长度都小于64字节 2. list对象保存的元素数量小于512个, 不能满足这两个条件的hash对象需要使用hashtable编码

Note:这两个条件的上限值是可以修改的,可查看配置文件hash-max-zaiplist-value和hash-max-ziplist-entries

<br> ## Set对象: Set对象的编码可以为intset或者hashtable + intset编码:使用整数集合作为底层实现,set对象包含的所有元素都被保存在intset整数集合里面 + hashtable编码:使用字典作为底层实现,字典键key包含一个set元素,而字典的值则都为null

inset编码Set对象结构:

	redis> SAD number  1 3 5 

file

hashtable编码Set对象结构:

redis> SAD Dfruits  “apple”  "banana" " cherry"

file

Set对象的编码转换:

使用intset编码: 1. set对象保存的所有元素都是整数值 2. set对象保存的元素数量不超过512个 不能满足这两个条件的Set对象使用hashtable编码

ZSet对象

ZSet对象的编码 可以为ziplist或者skiplist ziplist编码,每个集合元素使用相邻的两个压缩列表节点保存,一个保存元素成员,一个保存元素的分值,然后根据分数进行从小到大排序。

ziplist编码的ZSet对象结构:

Redis>ZADD price 8.5 apple 5.0 banana 6.0 cherry

file

skiplist编码的ZSet对象使用了zset结构,包含一个字典和一个跳跃表

Type struct zset{

	Zskiplist *zsl;
	dict *dict;
	...
}

skiplist编码的ZSet对象结构

file

ZSet对象的编码转换

当ZSet对象同时满足以下两个条件时,对象使用ziplist编码 1. 有序集合保存的元素数量小于128个 2. 有序集合保存的所有元素的长度都小于64字节 不能满足以上两个条件的有序集合对象将使用skiplist编码。

**Note:**可以通过配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule

© 著作权归作者所有

c
粉丝 13
博文 25
码字总数 75978
作品 0
深圳
私信 提问
Redis不同数据类型的的数据结构实现

原文:Redis不同数据类型的的数据结构实现 我们知道Redis支持五种数据类型, 分别是字符串、哈希表(map)、列表(list)、集合(set)和有序集合,和Java的集合框架类似,不同数据类型的数据...

杰克.陈
2017/12/19
0
0
redis数据结构之一:链表

链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。redis提供五种数据结构:String、hash、list、set、sorted set。这五大数据类型底层...

mypsf
2016/10/24
336
0
浅谈Redis五种数据结构的底层原理

概念 Redis作为一个开源的用C编写的非关系型数据库,基于优秀的CRUD效率,常用于软件系统的缓存,其本身提供了以下五种数据格式: string:字符串 list:列表 hash:散列表 set:无序集合 zs...

中关村的老男孩
06/18
5.4K
9
redis数据类型

Redis的key Redis的key是字符串类型,如果中间有空格或者转义字符等,要用“”。 1:命名建议:对象类型:对象ID:对象属性 2:多个单词之间以“.”来分隔 3:Key的命名,应该在可读的情况下,...

daydayup08
2016/04/22
57
0
ITOO---“秒杀”选课之Redis序列化

1.我的选课 在进行选课活动中了为了尽量减少客户端和数据库的连接次数,在实现的思路是这样设计的:客户端的请求优先访问Redis缓存空间,如果Redis中没有则从数据库中加载,并添加到Redis中。...

mengdonghui123456
2017/08/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JDBC+C3P0+DBCP 基本使用

1.概述 这篇文章主要说了JDBC的基本使用,包括Statement,PreparedStatement,JDBC的连接,Mysql创建用户创建数据表,C3P0的连接与配置,DBCP的连接与配置. 2.mysql的处理 这里的JDBC使用Mysql作为...

Blueeeeeee
今天
7
0
MVC Linux下开发及部署

linux使用的是 Ubuntu 64 位 18.04.2 LTS 首先复制C:\Program Files (x86)\Embarcadero\Studio\20.0\PAServer 下 LinuxPAServer20.0.tar.gz 到 linux 目录下 运行链接编译程序 delphi环境配置......

苏兴迎
今天
11
0
3.控件及其属性

1.文本 2.按钮

横着走的螃蟹
今天
9
0
安装Genymotion模拟器慢的解决方案

第一步点击下载, C:\Users\Administrator\AppData\Local\Genymobile\genymotion.log 中搜索 ova 会发现这个文件 使用迅雷下载即可. 在 虚拟机中导入这个.ova 文件 即可安装...

chenhongjiang
今天
6
0
4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了)

你好,我是彤哥,本篇是netty系列的第四篇。 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识。 简介 上一章我们一起学习了Java中的BIO/NIO/AIO的故事,本章将带着大家一起使用纯纯的N...

彤哥读源码
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部