Redis对象
概述
Redis并没有使用基础数据结构去实现键值数据库,而是基于数据结构封装了一个个对象。
类型和编码
由于Redis是键值数据库,所以每次存储数据时,至少包含两个对象,即K、V对应的对象。其数据结构如下所示
class RedisObject{
// 类型
int type;
// 编码
int encoding;
// 指向底层数据结构指针
Object ptr;
// 引用计数
int refcount;
// 上次被访问时间
int lru;
}
类型(type),常用类型如下
类型常量 名称 REDIS_STRING 字符串 REDIS_LIST 链表 REDIS_HASH 哈希表 REDIS_SET 集合 REDIS_ZSET 有序集合 编码常量(encoding),如下
类型 编码对应的底层数据结构 REDIS_ENCODING_INT long类型的整数 REDIS_ENCODING_EMBSTR embstr
格式的简单动态字符串实现REDIS_ENCODING_RAW 简单动态字符串 REDIS_ENCODING_HT 哈希表 REDIS_ENCODING_LINKEDLIST 双端链表 REDIS_ENCODING_ZIPLIST 压缩链表和字典 REDIS_ENCODING_SKIPLIST 跳跃表 REDIS_ENCODING_INTSET 整数集合 redis中每种对象至少拥有两种实现。对应的关系如下
redis对象 编码类型 描述 REDIS_STRING REDIS_ENCODING_EMBSTR embstr
编码的stringREDIS_STRING REDIS_ENCODING_ROW 简单动态字符串实现的string REDIS_STRING REDIS_ENCODING_INT 整数值编码的string REDIS_LIST REDIS_ENCODING_LINKEDLIST 双端链表实现的链表 REDIS_LIST REDIS_ENCODING_ZIPLIST 压缩链表实现的链表 REDIS_HASH REDIS_ENCODING_HT 哈希表实现的字典 REDIS_HASH REDIS_ENCODING_ZIPLIST 压缩链表实现的字典 REDIS_SET REDIS_ENCODING_INTSET 整数集合实现的集合 REDIS_SET REDIS_ENCODING_HT 哈希表实现的集合 REDIS_ZSET REDIS_ENCODING_ZIPLIST 压缩链表实现的有序集合 REDIS_ZSET REDIS_ENCODING_SKIPLIST 跳表实现的有序集合 字符串对象:字符串对象在可用long类型表示时底层数据结构使用
int
编码,当无法使用long
表示并且字符长度小于32字节时使用embstr
编码,超过32字节时使用row
编码。embstr
编码和row
编码底层数据结构都是sds
,不同的是embstr
由于固定了最长只能是32字节,所以内存可以并且是一次性分配的,sds
和redisObject
在一段连续的内存中,而row
是分两次进行内存分配。列表对象:列表对象底层有两个实现一个是
LinkedList
,另一个是ZipList
,其实猜也能猜出,ZipList
是为了节省空间。当保存的字符串元素长度小于64并且元素数量小于512个时使用ZipList
作为底层实现,其它情况都是用LinkedList
作为底层实现。!哈希对象:哈希对象也有两个底层实现,一个是
ZipList
即压缩链表,另一个则是Ht
哈希表,压缩链表是每次都存两个元素即键值,键在前,值在后。编码转换的条件也是和列表对象一样,即不能满足zipList
条件的使用Ht
实现,即当保存的字符串元素长度小于64并且元素数量小于512个时使用ZipList
作为底层实现,否则使用Ht
实现。集合对象:集合对象的底层实现包括
Ht
和IntSet
,其中Ht
作为底层实现时,其键保存着集合元素,值都为Null
。当集合元素数量小于512时并且元素都为整数值时使用IntSet
作为底层实现,其他时候使用hashtable编码。有序集合对象:有序集合对象的底层实现时
ZipList
或SkipList
,使用ZipList
作为底层实现时,第一个值保存元素的值,第二个值保存元素的分值。此外无论是使用ZipList
还是使用SkipList
作为底层实现,都会创建一个Ht
用于保存分值到元素值的映射,从而达到O(1)的查询效率。
类型检查与命令多态
Redis的命令在执行前会对命令作类型检查,看当前数据对象是否支持当前命令,类似于Java中,众多实现类都继承了该类的方法,但由于不支持只能抛出Unsupported Exception
。同时,也可能存在多个实现类支持这一方法,这也是属于一种多态。
内存回收和对象共享
C语言中不存在内存回收机制,所以Redis自己实现了一套通过引用技术法的内存回收机制,在每个redisObject
中有一个refcount
属性记录了被引用的次数。除了为了回收之外,引用计数还可以做到内存共享的作用。即存在想用某一对象将其引用技术加1而不是直接删除。由于共享字符串的复杂性以及不确定性,使得Redis只会初始化从0-9999的整数作为共享对象。
对象空转时长
RedisObject
除了以上几个属性,还有一个就是lru
对象上次访问时间,通过当前时间减去lru
就可以获得对象的空转时长。
Redis对象的更多相关文章
- 【redis源码阅读】redis对象
结构定义 在redis中,对象的数据结构定义如下: typedef struct redisObject { unsigned type:4; unsgined encoding:4; uns ...
- Redis对象类型
Redis对象类型 Redis基于基础的数据结构创建的对象: 字符串对象. 列表对象. 哈希对象. 集合对象 有序集合对象. 对象回收:Redis对象系统实现了基于引用计数技术的内存回收机制,当程序不 ...
- Redis底层探秘(五):Redis对象
前面几篇文章,我们一起学习了redis用到的所有主要数据结构,比如简单动态字符串(sds).双端链表.字典.压缩列表.整数集合等等. redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这 ...
- Redis对象的设计与实现
一.Redis对象结构Redis中的每个对象都由一个redisObject结构表示: typedef struct redisObject { unsigned type;//类型 unsigned ...
- 面试官:你了解过Redis对象底层实现吗
上一章我们讲了Redis的底层数据结构,不了解的人可能会有疑问:这个和平时用的五大对象有啥关系呢?这一章我们就主要解释他们所建立的联系. 看这个文件之前,如果对ziplist.skiplist.int ...
- Redis之对象篇——Redis对象系统简介
Redis之对象篇--Redis对象系统简介 前言 之前几篇文章,简单介绍 Redis用到的所有主要数据结构,简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合.跳跃表. 图解Red ...
- Redis对象——字符串
文章导航-readme 前言 上一篇文章Redis之对象篇--Redis对象系统简介简单介绍了Redis的对象系统.Redis使用对象来表示数据库中的键和值每个对象都由一个redisObjec ...
- redis 对象
redis通过前面几篇的数据结构构键了一个对象系统,这个对象系统包含了字符串对象,列表对象,哈希对象,集合对象,有序集合对象 每一个对象都是一个redisobject typedef struct r ...
- Redis对象占用内存分析
当你往Redis中插入了一系统对象,如何分析这些对象的占用情况? 1.我们可以在Redis的控制台使用info命令来查看各项指标,其中有一项是Memory,可以通过存储前后的used_memory差异 ...
随机推荐
- Windows10 Dev - Background Execution
The Universal Windows Platform (UWP) introduces new mechanisms, which allow the applications to perf ...
- springmvc学习日志二
一.当接受的参数为日期类型时 1.建立jsp页面,向Controller类传入参数 1.1当传入的参数为单个时 <body> <form action="user/toDa ...
- vsftpd - FTP 服务器安装
由于要将本地程序上传至云服务器中,所以需要给云服务器端安装ftp服务器.记录一下ftp的安装过程,以便以后使用.服务器端所用系统为Ubuntu16.04. 1. 安装ftp服务器, apt-get i ...
- 11.SpringMVC之HttpMessageConverter
HttpMessageConverter简介 HTTP 请求和响应的传输是字节流,意味着浏览器和服务器通过字节流进行通信.但是,使用 Spring,controller 类中的方法返回纯 String ...
- 【转】关于DNS不得不说的一些事
转自:https://www.cnblogs.com/rjzheng/p/11395695.html 引言 今天我们来聊聊DNS.所谓域名系统(Domain Name System缩写DNS,Doma ...
- VS在调试桌面程序时,cout到控制台方法
参考博客:https://blog.csdn.net/xinxinsky/article/details/80733400 C++桌面程序设置 Properties -> Build Event ...
- Linux档案权限篇之一
一.查看档案的属性 "ls" 第一列为档案的权限: d:代表是目录 -:代表是文件 l:代表是连接文件(相当于windows里面的快捷方式) b:代表块设备(如硬盘) c:代表字符 ...
- 一文读懂Lua元表
元表 Lua语言中的每种类型的值都有一套可预见的操作集合.例如,我们可以将数字相加,可以连接字符串,还可以在表中插入键值对等,但是我们无法将两个表相加,无法对函数作比较,也无法调用一个字符串,除非使用 ...
- Docker私有镜像仓库Harbor
一.安装Harbor(离线安装包的方式安装) 1.解压离线包 2.进入harbor目录中编辑harbor.yml 3.安装docker-compose yum -y install docker-co ...
- Python - 导入的位置
导入的是什么 导入是将 Python 的一些功能函数放到当前的脚本中使用 不导入的功能无法直接在当前脚本使用(除了 python 自带的内置函数) Python 有很多第三方功能,假设想要使用,都必须 ...