Redis-对象

在以前的文章中,我们介绍了 Redis 用到的主要数据结构,比如简单动态字符串、双端链表、字典、压缩列表、整数集合。

然而 Redis 并没有直接使用这些数据结构来实现键值对的数据库,而是在这些数据结构之上又包装了一层 RedisObject(对象),RedisObject 有五种对象:字符串对象、列表对象、哈希对象、集合对象和有序集合对象。

还是跟以前一样,看几个问题:

  • 使用 RedisObject 对象而不是直接使用双端队列、双端链表等数据结构,有什么好处呢?
  • RedisObject 的具体结构是什么?
  • 五种对象(string、hash、list、set、sort set)对应的 RedisObject 对象有何不同,底层使用的数据结构是什么?

使用 RedisObject 的好处

使用 RedisObject 的优点主要有两个,分别是:

  1. 通过不同类型的对象,Redis 可以在执行命令之前,根据对象的类型来判断一个对象是否可以执行给定的命令。
  2. 我们可以针对不同的使用场景,为对象设置不同的实现,从而优化内存或查询速度。

RedisObject 的具体结构是什么?

RedisObject 的源码如下:

typedef struct redisObject {

    // 类型
unsigned type:4; // 编码
unsigned encoding:4; // 对象最后一次被访问的时间
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */ // 引用计数
int refcount; // 指向实际值的指针
void *ptr; } robj;

下面分别解释一下各个字段的含义:

  1. type

    type 记录了对象的类型,所有的类型如下(出自《Redis设计与实现第二版》第八章:对象):



    对于 Redis 数据库保存的键值对来说,键一定是一个字符串对象,而值则可以使五种对象的其中一种。

  2. ptr 指针:指向对象的底层实现数据结构;

  3. encoding

    encoding 表示 ptr 指向的具体数据结构,即这个对象使用了什么数据结构作为底层实现。

    encoding 的取值范围如下(出自《Redis设计与实现第二版》第八章:对象):



    每种类型的对象都至少使用了两种不同的编码,对象和编码的对应关系如下(出自《Redis设计与实现第二版》第八章:对象):

  4. refcount

    refcount 表示引用计数,由于 C 语言并不具备内存回收功能,所以 Redis 在自己的对象系统中添加了这个属性,当一个对象的引用计数为0时,则表示该对象已经不被任何对象引用,则可以进行垃圾回收了。

    扩展一下:Java中由于引用计数法解决不了循环引用的问题,所以 Java 中使用了可达性分析算法。那么 Redis 有没有考虑循环引用的问题呢?

  5. lru:表示对象最后一次被命令程序访问的时间。

五种对象对应的 RedisObject

字符串对象(string)

字符串对象的 encoding 有三种,分别是:int、raw、embstr。

  1. 如果一个字符串对象保存的是整数值,并且这个整数值可以用 long 类型标识,那么字符串对象会讲整数值保存在 ptr 属性中,并将 encoding 设置为 int。

    假设有如下命令:set number 10086。那么 number 键对象的示意图如下(出自《Redis设计与实现第二版》第八章:对象):

  2. 如果字符串对象保存的是一个字符串值,并且这个字符串的长度大于 32 字节,那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值,并将对象的编码设置为 raw。

    使用 raw 存储字符串的示意图如下(出自《Redis设计与实现第二版》第八章:对象):

  3. 如果字符串对象保存的是一个字符串值,并且这个字符串的长度小于等于 32 字节,那么字符串对象将使用 embstr 编码的方式来保存这个字符串。

    使用 embstr 存储字符串的示意图如下(出自《Redis设计与实现第二版》第八章:对象):

既然有了 raw 的编码方式,为什么还会有 embstr 的编码方式呢?

因为 embstr 的编码方式有一些优点,如下:

  • embstr 编码将创建字符串对象所需的内存分配次数从 raw 编码的两次降低为一次。
  • 释放 embstr 编码的字符串对象只需要调用一次内存释放函数,而释放 raw 编码的字符串对象需要调用两次内存释放函数。
  • 因为 embstr 编码的字符串对象的所有数据都保存在一块连续的内存里面,所以这种编码的字符串对象比起 raw ,编码的字符串对象能够更好地利用缓存带来的优势。

哈希对象(hash)

哈希对象的编码有两种,分别是:ziplist、hashtable。

当哈希对象保存的键值对数量小于 512,并且所有键值对的长度都小于 64 字节时,使用压缩列表存储;否则使用 hashtable 存储。

哈希对象的压缩列表对应的示意图如下(出自《Redis设计与实现第二版》第八章:对象):

哈希对象的 hashtable 对应的示意图如下(出自《Redis设计与实现第二版》第八章:对象):

列表对象(list)

列表对象的编码有两种,分别是:ziplist、linkedlist。

ziplist(压缩列表)主要是为节省内存而设计的内存结构,它的优点就是节省内存,但缺点就是比其他结构要消耗更多的时间,所以 Redis 在数据量小的时候使用压缩列表存储。

当列表的长度小于 512,并且所有元素的长度都小于 64 字节时,使用压缩列表存储;否则使用 linkedlist 存储。

列表对象的压缩列表对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

列表对象的链表对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

集合对象(set)

集合对象的编码有两种,分别是:intset、hashtable。

intset(整数集合)主要是为节省内存而设计的内存结构,它的优点就是节省内存,但缺点就是比其他结构要消耗更多的时间,所以 Redis 在数据量小的时候使用整数集合存储。

当集合的长度小于 512,并且所有元素都是整数时,使用整数集合存储;否则使用 hashtable 存储。

集合对象的 intset 对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

集合对象的 hashtable 对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

有序集合对象(sort set)

有序集合对象的编码有两种,分别是:ziplist、skiplist。

当有序集合的长度小于 128,并且所有元素的长度都小于 64 字节时,使用压缩列表存储;否则使用 skiplist 存储。

有序集合对象的 ziplist 对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

有序集合对象的 skiplist 对应的示意图如下出自《Redis设计与实现第二版》第八章:对象):

Redis 学习笔记(篇五):对象(RedisObject)的更多相关文章

  1. Redis学习笔记(五) 基本命令:Hash操作

    原文链接:http://doc.redisfans.com/hash/index.html 学习前先明确一下概念,这里我们把Redis的key称作key(键),把数据结构hash中的key称为fiel ...

  2. Redis学习笔记(五)——数据结构之哈希(Hash)

    一.介绍 Redis hash是一个string类型的field和value的映射表,hash特别设于用于存储对象. Redis中每个hash可以存储232 - 1 键值对(40多亿). 基本命令: ...

  3. 【转】Redis学习笔记(五)如何用Redis实现分布式锁(2)—— 集群版

    原文地址:http://bridgeforyou.cn/2018/09/02/Redis-Dsitributed-Lock-2/ 单机版实现的局限性 在上一篇文章中,我们讨论了Redis分布式锁的实现 ...

  4. Redis学习笔记(五)- 数据类型之set类型

    Redis 的set是string类型的无序集合.set元素最大可以包含(2的32次方-1)个元素.set的是通过hash table实现的,所以添加,删除,查找的复杂度都是O(1).hash tab ...

  5. Redis 学习笔记(五)高可用之主从模式

    上一节提到了 Redis 的持久性,也就是在服务器实例宕机或故障时,拥有再恢复的能力.但是在这个服务器实例宕机恢复期间,是无法接受新的数据请求.对于整体服务而言这是无法容忍的,因此我们可以使用多个服务 ...

  6. Redis学习笔记(五)散列进阶

    HEXISTS key_name key(检查键key是否存在) HKEYS key_name(获得散列的所有键) HVALS key_name(获得散列的所有值) HINCRBY key_name ...

  7. Redis学习笔记(二) Redis 数据类型

    Redis 支持五种数据类型:string(字符串).list(列表).hash(哈希).set(集合)和 zset(有序集合),接下来我们讲解分别讲解一下这五种类型的的使用. String(字符串) ...

  8. Redis学习笔记一:数据结构与对象

    1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...

  9. redis学习笔记(详细)——高级篇

    redis学习笔记(详细)--初级篇 redis学习笔记(详细)--高级篇 redis配置文件介绍 linux环境下配置大于编程 redis 的配置文件位于 Redis 安装目录下,文件名为 redi ...

  10. Redis学习笔记(2)——Redis的下载安装部署

    一.下载Redis Redis的官网下载页上有各种各样的版本,如图 但是官网下载的Redis项目不正式支持Windows.如果需要再windows系统上部署,要去GitHub上下载.我下载的是Redi ...

随机推荐

  1. wamp大文件上传

    为什么上传大文件总是失败,但是上传小文件就没有问题.小编也不得其解,网上搜其原因,整理了一篇关于php上传大文件失败的原因和解决办法的文章,分享给大家. 下面分别是各种原因以及解决办法:第1种情况:文 ...

  2. python define function

    >>> def square(x): ... 'calculates the square of the number x.' ... return x*x ... >> ...

  3. 【概率论】3-3:累积分布函数(Cumulative Distribution Function)

    title: [概率论]3-3:累积分布函数(Cumulative Distribution Function) categories: Mathematic Probability keywords ...

  4. prometheus简单监控Linux,mysql,nginx

    prometheus安装 下载安装 #官网下载 解压即可使用 https://prometheus.io/download/ #docker 方式安装 sudo docker run -n prome ...

  5. 【java中的final关键字】

    转自:https://www.cnblogs.com/xiaoxi/p/6392154.html 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括成员变量 ...

  6. CentOS7.4中配置jdk环境

    参考:https://www.linuxidc.com/Linux/2016-09/135556.htm 1.下载jdk 首先创建安装包放置位置 mkdir -p /usr/local/java 然后 ...

  7. arcgis python pdf合并

    # -*- coding: cp936 -*- import arcpy, os, string #Read input parameters from script tool PDFList = s ...

  8. Facebook币Libra学习-5.Move组织目录

    Move是一种新的编程语言,旨在为Libra Blockchain提供安全可编程的基础. 组织 Move语言目录由五部分组成: 的虚拟机(VM),其中包含的字节码格式,字节码解释器,和基础设施执行事务 ...

  9. SQL-W3School-基础:SQL AND & OR 运算符

    ylbtech-SQL-W3School-基础:SQL AND & OR 运算符 1.返回顶部 1. AND 和 OR 运算符用于基于一个以上的条件对记录进行过滤. AND 和 OR 运算符 ...

  10. [Scikit-learn] *2.3 Clustering - DBSCAN: Density-Based Spatial Clustering of Applications with Noise

    http://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html#sklearn.cluster.DBSCAN ...