Redis原理 - RedisObject对象机制

news2024/10/5 22:23:10

原文首更地址,阅读效果更佳!

Redis原理 - RedisObject对象机制 | CoderMast编程桅杆icon-default.png?t=N5F7https://www.codermast.com/database/redis/redis-object.html

为什么会设计RedisObject

在 Redis 中,我们的操作都是使用指令进行,而这些的命令中,用于对键处理的命令占据一大部分。有些指令只能针对某些特定的类型,而有些指令却能够针对所有的类型。但是要正确实现这些命令,必须为不同类型的键设置不同的处理方式。比如删除一个列表键和删除一个字符串键的操作过程是不一样的,在底层就需要调用不同的视线方式。

集合类型有字典和整数集合两种不同的底层实现方式,而用户在对集合进行操作时,并不想关心具体的底层实现是什么样的,只要 Redis 能根据自己的指令,完成对应的功能即可,比如对元素进行添加、删除等操作,具体的实现底层对用户来说是透明的,不可见的。

所以 Redis 必须让每个键都带有类型信息, 并且带有其底层的编码方式,拥有这两个信息时,Redis 才能够准确无误的实现用户的指令。那么 RedisObject 对象起码就应该包含3个属性,类型信息、编码方式、实际数据。

#RedisObject

Redis 中的任意数据类型的键和值都会被封装为一个 RedisObject,也叫做 Redis 对象,在/src/server.h文件中实现如下:

typedef struct redisObject {
    unsigned type:4;        
    unsigned encoding:4;    // 共有 11 种编码方式,占据 4 个比特位
    unsigned lru:LRU_BITS;  /* LRU 表示该对象最后一次被访问的时间,其占用 24 个 bit 位,
                               便于判断空闲时间太久的key */
    int refcount;           // 对象引用计数器,计数器为 0 则说明对象无人引用,可以被回收。
    void *ptr;              // 指针,指向数据的真实存储空间地址。一般为 8 个字节
} robj;
  • unsigned type:4占 4 个 bit 位,分别是 string、list、set、zset、hash 对应 0 1 2 3 4
  • unsigned encoding:4共有 11 种编码方式,占据 4 个比特位
  • unsigned lru:LRU_BITSLRU 表示该对象最后一次被访问的时间,其占用 24 个bit 位,便于判断空闲时间太久的key
  • int refcount对象引用计数器,计数器为 0 则说明对象无人引用,可以被回收。
  • void *ptr指针,指向数据的真实存储空间地址。一般为 8 个字节

#编码方式

Redis 中会根据存储的数据类型不同,选择不同的编码方式,共包含 11 种不同类型:

编号编码方式说明
1OBJ ENCODING RAWraw编码动态字符串
2OBJ ENCODING INTLong类型的整数的字符串
3OBJ_ENCODING_HThash表(字典dict)
4OBJ ENCODING ZIPMAP已废弃
5OBJ_ENCODING_LINKEDLIST双端链表
6OBJ ENCODING ZIPLIST压缩列表
7OBJ_ENCODING INTSET整数集合
8OBJ ENCODING SKIPLIST跳表
9OBJ_ENCODING EMBSTRembstr的动态字符串
10OBJ_ENCODING QUICKLIST快速列表
11OBJENCODING STREAMStream流

#数据类型

Redis 中根据存储的数据类型不同,选择不同的编码方式。每种数据类型使用的编码方式如下:

数据类型编码方式编号说明
OBJ_STRINGint、embstr、raw0字符串
OBJ_LISTLinkedList和ZipList(3.2以前)、QuickList(3.2以后)1列表
OBJ_SETintset、HT2集合
OBJ_ZSETZipList、HT、SkipList3有序集
OBJ_HASHZipList、HT4哈希表

注意

这里只有 5 种基本类型,而没有提到 3 种特殊类型,是因为这三种特殊类型的底层是使用OBJ_STRING来实现的,并没有新的底层实现方式。

#命令处理

通过前面的描述,Redis 在执行命令时,需要判断所执行的数据类型和编码方式,则 Redis 执行一个处理数据类型命令的时候,Redis 执行以下步骤:

  1. 根据给定的key,在数据库字典中查找和他相对应的redisObject,如果没找到,就返回NULL
  2. 检查redisObject的type属性和执行命令所需的类型是否相符,如果不相符,返回类型错误
  3. 根据redisObject的encoding属性所指定的编码,选择合适的操作函数来处理底层的数据结构
  4. 返回数据结构的操作结果作为命令的返回值

比如现在执行LPOP命令:

#对象共享

Redis 一般会把一些常见的值放到一个共享对象中,这样可使程序避免了重复分配的麻烦,也节约了一些CPU时间。

Redis预分配的值对象如下

  • 各种命令的返回值,比如成功时返回的OK,错误时返回的ERROR,命令入队事务时返回的QUEUE,等等
  • 包括0 在内,小于REDIS_SHARED_INTEGERS的所有整数(REDIS_SHARED_INTEGERS的默认值是10000)

注意

共享对象只能被字典和双向链表这类能带有指针的数据结构使用,只有指针才能够指向任意的地址。而整数集合和压缩列表这些只能保存字符串、整数等实际数据的类型,则无法共享。

为什么redis不共享列表对象、哈希对象、集合对象、有序集合对象,只共享字符串对象?

  • 列表对象、哈希对象、集合对象、有序集合对象,本身可以包含字符串对象,复杂度较高。
  • 如果共享对象是保存字符串对象,那么验证操作的复杂度为O(1)
  • 如果共享对象是保存字符串值的字符串对象,那么验证操作的复杂度为O(N)
  • 如果共享对象是包含多个值的对象,其中值本身又是字符串对象,即其它对象中嵌套了字符串对象,比如列表对象、哈希对象,那么验证操作的复杂度将会是O(N的平方)
  • 如果对复杂度较高的对象创建共享对象,需要消耗很大的CPU,用这种消耗去换取内存空间,是不合适的。并且对象的复杂度过高,说明对象的个性较大,共性较少,则使用到该对象的次数和频率都会很低。

#引用计数器

RedisObject 中有 refcount 属性,为对象引用计数器,用于记录对象引用数量。

当计数器为 0 时,则代表该对象没有被引用,则就不会再被使用,那么说明该对象可以被删除销毁。

当新创建一个对象时,它的refcount属性被设置为1。

当对一个对象进行共享时,Redis 将这个对象的 refcount 加一。

当使用完一个对象后,或者消除对一个对象的引用之后,程序将对象的refcount减一。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/661151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python截取文件名教程

Python截取文件名教程 在Python编程中,经常需要从文件路径中截取出文件名。这可以让我们更容易地操作文件或数据集,并且使代码更加简洁易懂。在本教程中,我们将介绍如何使用Python截取文件名。 使用os模块 Python的os模块提供了许多与文件…

【C数据结构】静态顺序表_SeqList

目录 【1】数据结构概述 【1.1】什么是数据结构? 【1.2】数据结构分类 【1.3】数据结构术语 【2】数据结构特点 【3】静态顺序表 【3.1】静态顺序表概念及结构 【3.2】静态顺序表定义数据结构和接口 【3.3】静态顺序表初始化 【3.4】静态顺序表头插入 【…

C/C++内存管理(newdelete详解)

C/C内存管理 引言new与delete的使用内置类型自定义类型 new与delete的实现原理内置类型了解operator new与operator delete函数自定义类型 定位newnew&delete与malloc&free的区别总结 引言 在之前的C语言部分,我们已经介绍过内存中的存储区域的划分&#x…

FMQL在linux下GPIO的映射关系与使用

最近几年国产化芯片的使用如火如荼,部分国产手册说明杂且描述不清,尤其是一些映射关系使用文字描述非常不直观。博主在使用GPIO功能输出的时候反复看了几遍再去尝试控制耗费了不少时间。现结合相关文档总结GPIO映射表格,方便读者使用。 1、 …

【Spring Boot 】Spring Boot 统一功能处理

🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 前言 1. Spring 拦截器 1.1 自定义拦截器 1…

6月19日第壹简报,星期一,农历五月初二

6月19日第壹简报,星期一,农历五月初二坚持阅读,静待花开1. 未来10天江南华南等地多降雨过程,国家防总将防汛四级响应范围扩至八省份,加派工作组赴地方协助指导。2. “一天有四季、十里不同天”,“最美”独库…

LVS - DR集群

LVS - DR集群 数据包流向分析: (1)客户端发送请求到 Director Server(负载均衡器),请求的数据报文(源 IP 是 CIP,目标 IP 是 VIP)到达内核空间。 (2)Direct…

【VS2022】win 10 / win 11:Visual Studio 2022 社区版免费下载与安装

目录 一、Visual Studio 2022 下载 二、Visual Studio 2022 安装 三、Visual Studio 2022 快捷方式创建 四、Visual Studio 2022 使用 一、Visual Studio 2022 下载 Visual Studio 2022 官方下载https://visualstudio.microsoft.com/zh-hans/downloads/首先登陆 Visual Stu…

attention unet + cldice 论文总结

Blood Vessel Segmentation from Low-Contrast and Wide-Field Optical Microscopic Images of Cranial Window by Attention-Gate-Based Network论文总结 论文:Blood Vessel Segmentation by Attention-Gate-Based Network 目录 一、论文背景和出发点 二、创新点…

vue源码阅读之Observer

我们上次学习了vue数据驱动的概念,以及简单的vue怎么知道数据更新,然后采取行动的。今天我们就来继续深入学习,vue怎么把数据和视图给绑定在一起的,数据发生变化,视图怎么会自动发生变化的。 vue中的Observer 之前讲…

chatgpt赋能python:Python截取某一段文字

Python截取某一段文字 Python是最流行的编程语言之一,用于开发各种类型的应用程序,包括Web应用程序、桌面应用程序、游戏等。在本文中,我们将讨论如何使用Python截取某一段文字。这对于Web开发者和SEO专家非常有用,因为他们需要查…

【干货】Android系统定制基础篇:第八部分(增加以太网设置菜单、支持多摄像头、替换默认签名)

一、增加以太网设置菜单 Android 系统设置默认并没有以太网相关设置项,但以太网功能是支持的,因此我们仅仅需要增加设置界面即可。以太网设置界面如下: 修改 diff --git a/packages/apps/Settings/AndroidManifest.xml b/packages/apps/Se…

【第六次】21级计科计算机组成原理课外练习

【第六次】21级计科计算机组成原理课外练习 一、单选题二、多选题三、填空题 一、单选题 2-1 假定某计算机按字节编址,采用小端方式,有一个float型变量x的地址为0xffffc000,x12345678H,则在内存单元0xffffc001中存放的内容是 A.…

计算机网络和Linux网络

计算机网络和Linux网络 计算机网络概论 什么是计算机网络 计算机网络(结构上) 由节点(主机、网络交换设备设备)、边(通信设备)、协议构成协议:对等层的实体在通讯过程中应该遵守的规则的集合&…

软考A计划-网络工程师-易混淆知识汇总

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 👉关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

chatgpt赋能python:Python编程:如何隐藏输入以保护信息安全?

Python编程:如何隐藏输入以保护信息安全? 随着数字化时代的到来,人们越来越多地依赖于互联网和技术设备进行通信和交易。然而,信息安全成为越来越大的问题:黑客和其他恶意分子通过各种手段获取和利用个人信息。为保障…

【瑞萨RA_FSP】GPT—— PWM功能详解

文章目录 一、GPT比较匹配功能详解1. 锯齿波PWM模式(普通PWM模式)2. 三角波PWM模式1(波谷32位传输)3. 三角波PWM模式2(波峰和波谷32位传输)4. 三角波PWM模式3(波谷64位传输)5. 设置死…

【随机种子初始化】一个神经网络模型初始化的大坑

1 问题起因和经过 半年前写了一个模型,取得了不错的效果(简称项目文件1),于是整理了一番代码,保存为了一个新的项目(简称项目文件2)。半年后的今天,我重新训练这个整理过的模型&…

【C数据结构】带头双向循环链表_HDList

目录 带头双向循环链表_HDList 【1】链表概念 【2】链表分类 【3】带头双向循环链表 【3.1】带头双向循环链表数据结构与接口定义 【3.2】带头双向循环链表初始化 【3.3】带头双向循环链表开辟节点空间 【3.4】带头双向循环链表销毁 【3.5】带头双向循环链表头插 【3…

【C数据结构】带头单向非循环链表_HList

目录 带头单向非循环链表_HList 【1】链表概念 【2】链表分类 【3】有头单向非循环链表 【3.1】非循环链表数据结构与接口定义 【3.2】带头单向非循环链表初始化 【3.3】带头单向非循环链表释放空间 【3.4】带头单向非循环链表创建节点 【3.5】带头单向非循环链表头插…