概述

Redis并没有使用基础数据结构去实现键值数据库,而是基于数据结构封装了一个个对象。

类型和编码

由于Redis是键值数据库,所以每次存储数据时,至少包含两个对象,即K、V对应的对象。其数据结构如下所示

class RedisObject{
// 类型
int type;
// 编码
int encoding;
// 指向底层数据结构指针
Object ptr;
// 引用计数
int refcount;
// 上次被访问时间
int lru;
}
  1. 类型(type),常用类型如下

    类型常量 名称
    REDIS_STRING 字符串
    REDIS_LIST 链表
    REDIS_HASH 哈希表
    REDIS_SET 集合
    REDIS_ZSET 有序集合
  2. 编码常量(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编码的string
    REDIS_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 跳表实现的有序集合
  3. 字符串对象:字符串对象在可用long类型表示时底层数据结构使用int编码,当无法使用long表示并且字符长度小于32字节时使用embstr编码,超过32字节时使用row编码。embstr编码和row编码底层数据结构都是sds,不同的是embstr由于固定了最长只能是32字节,所以内存可以并且是一次性分配的,sdsredisObject在一段连续的内存中,而row是分两次进行内存分配。

  4. 列表对象:列表对象底层有两个实现一个是LinkedList,另一个是ZipList,其实猜也能猜出,ZipList是为了节省空间。当保存的字符串元素长度小于64并且元素数量小于512个时使用ZipList作为底层实现,其它情况都是用LinkedList作为底层实现。!

  5. 哈希对象:哈希对象也有两个底层实现,一个是ZipList即压缩链表,另一个则是Ht哈希表,压缩链表是每次都存两个元素即键值,键在前,值在后。编码转换的条件也是和列表对象一样,即不能满足zipList条件的使用Ht实现,即当保存的字符串元素长度小于64并且元素数量小于512个时使用ZipList作为底层实现,否则使用Ht实现。

  6. 集合对象:集合对象的底层实现包括HtIntSet,其中Ht作为底层实现时,其键保存着集合元素,值都为Null。当集合元素数量小于512时并且元素都为整数值时使用IntSet作为底层实现,其他时候使用hashtable编码。

  7. 有序集合对象:有序集合对象的底层实现时ZipListSkipList,使用ZipList作为底层实现时,第一个值保存元素的值,第二个值保存元素的分值。此外无论是使用ZipList还是使用SkipList作为底层实现,都会创建一个Ht用于保存分值到元素值的映射,从而达到O(1)的查询效率。

类型检查与命令多态

Redis的命令在执行前会对命令作类型检查,看当前数据对象是否支持当前命令,类似于Java中,众多实现类都继承了该类的方法,但由于不支持只能抛出Unsupported Exception。同时,也可能存在多个实现类支持这一方法,这也是属于一种多态。

内存回收和对象共享

C语言中不存在内存回收机制,所以Redis自己实现了一套通过引用技术法的内存回收机制,在每个redisObject中有一个refcount属性记录了被引用的次数。除了为了回收之外,引用计数还可以做到内存共享的作用。即存在想用某一对象将其引用技术加1而不是直接删除。由于共享字符串的复杂性以及不确定性,使得Redis只会初始化从0-9999的整数作为共享对象。

对象空转时长

RedisObject除了以上几个属性,还有一个就是lru对象上次访问时间,通过当前时间减去lru就可以获得对象的空转时长。

Redis对象的更多相关文章

  1. 【redis源码阅读】redis对象

    结构定义 在redis中,对象的数据结构定义如下: ​typedef struct redisObject { ​unsigned type:4; ​unsgined encoding:4; ​uns ...

  2. Redis对象类型

    Redis对象类型 Redis基于基础的数据结构创建的对象: 字符串对象. 列表对象. 哈希对象. 集合对象 有序集合对象. 对象回收:Redis对象系统实现了基于引用计数技术的内存回收机制,当程序不 ...

  3. Redis底层探秘(五):Redis对象

    前面几篇文章,我们一起学习了redis用到的所有主要数据结构,比如简单动态字符串(sds).双端链表.字典.压缩列表.整数集合等等. redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这 ...

  4. Redis对象的设计与实现

    一.Redis对象结构Redis中的每个对象都由一个redisObject结构表示: typedef struct redisObject { unsigned type;//类型 unsigned ...

  5. 面试官:你了解过Redis对象底层实现吗

    上一章我们讲了Redis的底层数据结构,不了解的人可能会有疑问:这个和平时用的五大对象有啥关系呢?这一章我们就主要解释他们所建立的联系. 看这个文件之前,如果对ziplist.skiplist.int ...

  6. Redis之对象篇——Redis对象系统简介

    Redis之对象篇--Redis对象系统简介 前言     之前几篇文章,简单介绍 Redis用到的所有主要数据结构,简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合.跳跃表. 图解Red ...

  7. Redis对象——字符串

    文章导航-readme 前言     上一篇文章Redis之对象篇--Redis对象系统简介简单介绍了Redis的对象系统.Redis使用对象来表示数据库中的键和值每个对象都由一个redisObjec ...

  8. redis 对象

    redis通过前面几篇的数据结构构键了一个对象系统,这个对象系统包含了字符串对象,列表对象,哈希对象,集合对象,有序集合对象 每一个对象都是一个redisobject typedef struct r ...

  9. Redis对象占用内存分析

    当你往Redis中插入了一系统对象,如何分析这些对象的占用情况? 1.我们可以在Redis的控制台使用info命令来查看各项指标,其中有一项是Memory,可以通过存储前后的used_memory差异 ...

随机推荐

  1. CSS基本语法(慕课网学习笔记)

    CSS的声明,内外联样式以及CSS的优先级 css学习.html <!DOCTYPE html> <html lang="en"> <head> ...

  2. Mysql 中隐式转换

    案例一:条件字段函数操作 假设你现在维护了一个交易系统,其中交易记录表 tradelog 包含交易流水号(tradeid).交易员 id(operator).交易时间(t_modified)等字段.为 ...

  3. JDK 5.0新特性

    时间:2016-11-5 12:03 JDK5.0新特性    泛型.枚举.静态导入.自动拆装箱.增强for循环.可变参数1.Junit单元测试    测试的对象是类中的一个方法.    junit不 ...

  4. openCV入门系列教学(一) 图像的读取、展示与保存

    序言 笔者最近做了两个CV领域的项目,因为数据量不足所以主要使用的是传统的CV方法.这时候不得不夸一句opencv库,让复杂的算法原理变得如此简单(调包调参侠表示很骄傲).所以闲暇下来对opencv的 ...

  5. uni-app 小程序从零开始的开发流程

    前言 本文基于 HBuilderX 3.1.22 + 微信开发者工具 1.05.2106300为主要内容进行说明. 文档版本:1.0.0 更新时间:2021-09-03 15:32 一.准备 uni- ...

  6. Java编程:为什么Class实例可以不是全局唯一

    通过定义两个类加载器加载同一字节码文件来证明Class实例为什么不是全局唯一的 1.将一个名为Demo(没有后缀)的字节码文件放在D盘根目录 2.定义两个类加载器 自定义ClassLoader三要素: ...

  7. Stream流用于按照对象中某一属性来对集合去重+简单数据类型集合的去重

    上次对Stream流来进行分组的文章很多人看,想看的可以来这: Stream流来进行集合分组 这次小编又带来Stream的去重,话不多数,直接上代码: 这是对简单数据类型的去重 //字符串集合进行简单 ...

  8. 小白2分钟学会Visual Studio将引用包打包到NuGet上

    前言 之前我们说 10分钟学会Visual Studio将自己创建的类库打包到NuGet进行引用(net,net core,C#),过程有些许繁琐,并且需要有一定的基础. 怎么办呢,不慌,看法宝. 两 ...

  9. MySQL——select语句

    select: 基本语法:select 列名 或 * from 对象(表.视图...) where: = > < <> != like ----> like 'old%' ...

  10. python 常用的文件操作命令

    一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 2.返回指定目录下的所有文件 ...