Redis源码分析(基于Redis7,对比Redis6)

news2024/11/13 15:00:27

PS: redis7.0.9版本的

1.Redis 源代码分类

1.1Redis 基本的数据结构

  1. 基础
    • Redis对象object.c
    • 字符串t_string.c
    • 列表t_list.c
    • 字典t_hash.c
    • 集合及有序集合t_set.c和z_set.c
    • 数据流 t_stream
      • 底层实现结构 listpack.c 和 rax.c
  2. 简单动态字符串 sds.c
  3. 整数集合 intset.c
  4. 压缩列表 ziplist.c
  5. 快速链表 quicklist.c
  6. listpack
  7. 字典 dict.c

1.2 Redis 数据库的实现

  • 数据库的底层实现 db.c
  • 持久化 rdb.c 和 aof.c

1.3 Redis服务端和客户端实现

  • 事件驱动 ae.c 和 ae_epoll.c
  • 网络连接 anet.c 和 networking.c
  • 服务端服务 server.c
  • 客户端程序 redis-cli.c

1.4 其它

  • 主从复制 replication.c
  • 哨兵 sentinel.c
  • 集群 cluster.c
  • 其他数据结构,如 hyperloglog.c , geo.c等
  • 其他功能, 如 pub/sub 、Lua 脚本

2. Redis 字典数据库KV键值对

2.1 怎么实现键值对(k-v)数据库

  • key 一般都是String类型的字符串对象
  • value 类型则为redis对象(redisObject)
    • value可以是字符串对象
    • 也可以是集合数据类型的对象,List对象、Hash对象、Set对象和Zset对象

在这里插入图片描述

2.2 十大类型说明

  • 传统的五大类型
    • String
    • List
    • Hash
    • Set
    • Zset
  • 另外五大类型
    • bitmap
      • 实质String
    • hyperLogLog
      • 实质String
    • GEO
      • 实质 Zset
    • Stream
      • 实质Stream
    • BITFIELD
      • 看具体key

在这里插入图片描述

2.3 Redis定义了redisObject结构体来表示传统的五大类型

Redis中每个对象都是一个 redisObject结构

1. 字典、k-v是什么

  • 每个键值对都会有一个dictEntry

  • dict.h源码文件

    在这里插入图片描述

    • dictEntry 表示哈希表节点的结构。存放了void *key和void *value的指针
    • *key 指向String对象
    • *value 既能指向String对象也能指向集合类型的对象(比如List + Hash + Set + Zset 对象)
    • 备注
      • void *key 和 void *value 指针指向的是内部抽象类的Redis对象,Redis中的每个对象都由 redisObject 构成
  • 重点:从dictEntry 到 RedisObject

    在这里插入图片描述

在这里插入图片描述

2. 键值对如何保存进Redis并进行读取操作,O(1)复杂度

在这里插入图片描述

3. redisObject + Redis数据类型+Redis所有编码(底层)方式三者之间的关系

在这里插入图片描述

3.五大结构底层C语言源码分析

3.1Redis数据类型与数据结构总纲图

1.总体数据结构大纲

  • SDS 动态字符串
  • 双向链表
  • 压缩列表 ziplist
  • 哈希表 hashtable
  • 跳表 skiplist
  • 整数集合 intset
  • 快速列表 quicklist
  • 紧凑列表 listpack

2.Redis6 与 Redis7

在这里插入图片描述

在这里插入图片描述

3.2 简单的命令分析

  • 每个键值对都会有一个 dictEntry

  • set hello world

    • 查看类型 type hello
    • 查看编码 object encoding hello

在这里插入图片描述

  • 因为Redis是KV键值对的数据库,每个键值对都会有一个dictEntry(源码位置:dict.h),里面指向了key和value的指针,next 指向下一个 dictEntry。

  • key 是字符串,但是 Redis 没有直接使用 C 的字符数组,而是存储在redis自定义的 SDS中。value 既不是直接作为字符串存储,也不是直接存储在 SDS 中,而是存储在redisObject 中。实际上五种常用的数据类型的任何一种,都是通过 redisObject 来存储的。

在这里插入图片描述

3.3 redisObject结构的作用

在这里插入图片描述

  • 4位的type表示具体的数据类型

  • 4位的encoding表示该类型的物理编码方式见下表,同一种数据类型可能有不同的编码方式。(比如String就提供了3种:int embstr raw)

    在这里插入图片描述

  • lru字段表示当内存超限时采用LRU算法清除内存中的对象

  • refcount表示对象的引用计数

  • ptr指针指向真正的底层数据结构的指针

例如 set age 17

在这里插入图片描述

type类型
encoding编码,此处是数字类型
lru最近被访问的时间
refcount等于1,表示当前对象被引用的次数
ptrvalue的值是多少,当前就是17

3.4 经典五大数据结构解析

3.4.1. 各个类型的数据结构的编码映射和定义

在这里插入图片描述

3.4.2. String 数据结构介绍

1.三大物理编码方式

RedisObject 内部对应3大物理编码

在这里插入图片描述

int

  1. 保存long型(长整型)的64位(8个字节)有符号整数

  2. 最多19位

在这里插入图片描述

  1. 只有整数才会使用int,如果是浮点数,Redis内部其实先将浮点数转化为字符串值,然后再保存

embstr

代表embstr 格式的 SDS(Simple Dynamic String 简单动态字符串),保存长度小于44字节的字符串

raw

保存长度大于44字节的字符串

2. 三大物理编码案例

测试

在这里插入图片描述

C语言中字符串的展现

在这里插入图片描述

SDS简单动态字符串
  • sds.h 源码分析

在这里插入图片描述

  • 说明

在这里插入图片描述

  • Redis中字符串的实现,SDS有多种结构(sds.h)

    • define SDS_TYPE_5 (2^5=32byte)

      define SDS_TYPE_8 (2 ^ 8=256byte)

      define SDS_TYPE_16 (2 ^ 16=65536byte=64KB)

      define SDS_TYPE_32 (2 ^ 32byte=4GB)

      define SDS_TYPE_64 2的64次方byte=17179869184G用于存储不同的长度的字符串。

    • len 表示 SDS 的长度,使我们在获取字符串长度的时候可以在 O(1)情况下拿到,而不是像 C 那样需要遍历一遍字符串。

      alloc 可以用来计算 free 就是字符串已经分配的未使用的空间,有了这个值就可以引入预分配空间的算法了,而不用去考虑内存分配的问题。

      buf 表示字符串数组,真存数据的。

Redis 为什么重新设计了一个SDS数据结构?

因为C里面没有Java的String类型,只能靠char[]来实现,字符串在C中的存储方式,想要获取【Redis】的长度,需要从头开始遍历,直到遇到 ‘\0’ 为止,所以Redis自己构建了一种名为简单动态字符串SDS(simple dynamic string)的抽象类型,并将SDS作为Redis的默认字符串

在这里插入图片描述

CSDS
字符串长度处理需要从头开始遍历,直到遇到 ‘\0’ 为止,时间复杂度O(N)记录当前字符串的长度,直接读取即可,时间复杂度 O(1)
内存重新分配分配内存空间超过后,会导致数组下标越级或者内存分配溢出空间预分配:SDS 修改后,len 长度小于 1M,那么将会额外分配与 len 相同长度的未使用空间。如果修改后长度大于 1M,那么将分配1M的使用空间。 惰性空间释放:有空间分配对应的就有空间释放。SDS 缩短时并不会回收多余的内存空间,而是使用 free 字段将多出来的空间记录下来。如果后续有变更操作,直接使用 free 中记录的空间,减少了内存的分配。
二进制安全二进制数据并不是规则的字符串格式,可能会包含一些特殊的字符,比如 ‘\0’ 等。前面提到过,C中字符串遇到 ‘\0’ 会结束,那 ‘\0’ 之后的数据就读取不上了根据 len 长度来判断字符串结束的,二进制安全的问题就解决了
set k1 v1 底层的调用关系(对应三大编码)

在这里插入图片描述

INT编码格式

当字符串键值的内容可以用一个64位有符号整形来表示时,Redis会将键值转化为long型来进行存储,此时即对应 OBJ_ENCODING_INT 编码类型。内部的内存结构表示如下:

在这里插入图片描述

Redis 启动时会预先建立 10000 个分别存储 0~9999 的 redisObject 变量作为共享对象,这就意味着如果 set字符串的键值在 0~10000 之间的话,则可以 **直接指向共享对象 而不需要再建立新对象,此时键值不占空间!**set k1 123set k2 123

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

EMBSTR编码格式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

对于长度小于 44的字符串,Redis 对键值采用OBJ_ENCODING_EMBSTR 方式,EMBSTR 顾名思义即:embedded string,表示嵌入式的String。从内存结构上来讲 即字符串 sds结构体与其对应的 redisObject 对象分配在同一块连续的内存空间,字符串sds嵌入在redisObject对象之中一样。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

RAW编码格式

在这里插入图片描述

当字符串的键值为长度大于44的超长字符串时,Redis 则会将键值的内部编码方式改为OBJ_ENCODING_RAW格式,这与OBJ_ENCODING_EMBSTR编码方式的不同之处在于,此时动态字符串sds的内存与其依赖的redisObject的内存不再连续了

在这里插入图片描述

补充:

对于embstr,由于其实现是只读的,因此在对embstr 对象进行修改时,都会先转化为raw 再进行修改,因此,只要是修改 embstr 对象,修改后的对象一定是 raw, 无论是否达到了44个字节

流程图

结论:
  • 只有整数才会使用 int,如果是浮点数, Redis 内部其实先将浮点数转化为字符串值,然后再保存。

  • embstr 与 raw 类型底层的数据结构其实都是 SDS (简单动态字符串,Redis 内部定义 sdshdr 一种结构)。

那这两者的区别见下图:

1 intLong类型整数时,RedisObject中的ptr指针直接赋值为整数数据,不再额外的指针再指向整数了,节省了指针的空间开销。
2 embstr当保存的是字符串数据且字符串小于等于44字节时,embstr类型将会调用内存分配函数,只分配一块连续的内存空间,空间中依次包含 redisObject 与 sdshdr 两个数据结构,让元数据、指针和SDS是一块连续的内存区域,这样就可以避免内存碎片
3 raw当字符串大于44字节时,SDS的数据量变多变大了,SDS和RedisObject布局分家各自过,会给SDS分配多的空间并用指针指向SDS结构,raw 类型将会调用两次内存分配函数,分配两块内存空间,一块用于包含 redisObject结构,而另一块用于包含 sdshdr 结构

在这里插入图片描述

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

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

相关文章

【dp】最长递增子序列

文章目录 方法一:动态规划方法二:贪心 二分查找构造最长递增子序列 方法一:动态规划 dp[i]:末尾元素为arr[i]的最长子序列的长度 从0遍历到i - 1,若遍历到的元素小于当前值arr[i],表示当前值arr[i]可以和…

国考省考行测:词句理解,词的对象指代,就近原则,主语一致法,语意语境分析上下文找出指代含义

国考省考行测:词句理解,词的对象指代,就近原则,主语一致法,语意语境分析上下文找出指代含义 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带行测和申论,而常规国…

3年100亿!苏宁易购与倍科达成重磅战略合作

紧抓消费复苏机遇,家电行业迎来重磅合作。4月20日,苏宁易购与国际知名家电品牌倍科在南京召开战略合作发布会,共同宣布升级战略合作伙伴关系。双方将围绕3年100亿战略合作目标开展独家品牌授权、发起“BIS”计划、打造生态开放平台、升级用户…

5G基站外市电改造建设方案 (ppt可编辑)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除 外市电定义及分类 定义:由供电部门提供的专用高压电源或非专用高压电源或低压电源均称为市电。分类: (1)按电压等级分类 ①提供…

贝叶斯学习(Bayesian Learning)基础篇

Bayesian Learning 前言Motivation and IntroductionThink about Spam Filtering.先验概率后验概率似然度边际概率 Basic assumptionRelevancePractical diculties Bayes TheoremProbability: random eventsBayesian Learning Maximum A Posteriori HypothesisBayes Optimal Cl…

合同管理的6个最佳实践

合同管理不善会使你的合同流程效率低下,并产生负面影响: -收入损失 谈判缓慢、审批延迟和里程碑缺失等低效合同代价高昂。如果没有办法自动跟踪最后期限,并得到通知来执行时间敏感的行动,就会有错过最后期限的风险。 -协作和…

数组【有点难,要注重实战】

目录 1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的存储 3. 数组越界4. 数组作为函数参数4.1 冒泡排序函…

JavaEE-一文了解IP协议与IP地址

目录 IP协议什么是IP地址IP地址的组成动态分配IPNAT机制(网络地址转换) IP协议 IP协议是不可靠、无连接的 不可靠:表示IP协议不能保证IP数据报能成功的到达目的地。IP仅提供传输服务,任何可靠性的要求都必须由上层来提供(如TCP)。如果传输过…

【C++|排序算法】冒泡、快排、归并、堆排序算法模版

目录 简介冒泡排序快速排序归并排序堆排序结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国…

字节跳动五面都过了,结果被刷了,问了hr原因竟说是...

摘要 说在前面,面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到几个原因:1、虚报工资,比实际高30%;2、有更好的人选,这个可能性不大&…

反垃圾邮件产品技术要求

声明 本文是学习信息安全技术 反垃圾邮件产品技术要求和测试评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 反垃圾邮件产品技术要求 引言 为指导反垃圾邮件产品的研制、生产、测试和评价工作的开展,本标准依据《信息技术 安全技…

基于Spring注解 + MyBatis + Servlet 实现数据库交换的小小Demo

基于Spring注解 MyBatis Servlet 实现数据库交换的小小Demo 第一步 创建web 项目&#xff0c;这一步省略&#xff0c;有不会的可以参考之前发布的文档 第二步 配置pom.xml文件 <dependencies><!-- Spring常用依赖 --><dependency><groupId>org.spr…

SpringCloud --- Eureka注册中心

一、场景 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图 思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c;order-service调用时该…

【LeetCode】剑指 Offer 67. 把字符串转换成整数 p318 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/ 1. 题目介绍&#xff08;67. 把字符串转换成整数&#xff09; 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 …

day1 什么是互联网

目录 计算机网络的定义与分类 网络的网络 互联网的组成 互联网的边缘部分 互联网基础结构发展的三个阶段 第一阶段&#xff08;1969 - 1990&#xff09; 第二阶段&#xff08;1985 - 1993&#xff09; 第三阶段&#xff08;1993 - 现在&#xff09; 20世纪90年代&#xff…

项目经验总结——送给测试岗做项目的朋友们

目录 前言 1、项目排期时的时间预估能力欠佳 2、QA写单元测试 3、集成测试方案不够精简 4、排了优先级也很难取舍 5、搭完redis集群却不了解redis运行机制 总结 结语 前言 最近负责的L项目从3月初开始开发到6月底正式上线&#xff0c;这是我在工作快1年时间里第一次独…

机械键盘、口袋打印机,万元奖金等你拿!「万象格新」AI绘画X海报设计大赛即将开启...

号外&#xff01;「万象格新」大赛开启 如果阳光暖到你心里&#xff0c;那一定是一格在想你~ 春夏交替&#xff0c;万物焕发生机&#xff0c;明媚色彩娱情惬意 在这样一个美好的时节 如果你&#xff1a; 心中荡漾着色彩斑斓的 AI 绘画创意 想要 show 出独到的审美与非凡设计能力…

【系统集成项目管理工程师】项目干系人管理

&#x1f4a5;十大知识领域&#xff1a;项目干系人管理 项目干系人管理包括以下 4 个过程: 识别干系人规划干系人管理管理干系人参与控制干系人参与 一、识别干系人 输入工具与技术输出项目章程采购文件事业环境因素组织过程资产组织相关会议专家判断干系人分析干系人登记册 …

servlet(1)—javaEE

文章目录 1.认识servlet2.使用servlet2.1创建项目2.2引入依赖2.3创建目录2.4编写代码2.5打包2.6部署2.7运行2.8验证 3.开发步骤4.部署方式4.1打包4.2安装插件 5.访问出错的情况5.1 4045.2 4055.3其他 6.servlet的三大生命周期方法7.servlet api7.1HttpServlet7.2HttpServletReq…

想攀登金融领域高峰,中国人民大学与加拿大女王大学金融硕士是重要途径

每个人都希望自己的职场攀登是优质路线&#xff0c;最短路线。金融业招聘注重学历&#xff0c;最早外资投资银行招聘只要清北复交&#xff0c;现在知名金融机构工作也只招985。还有一个特点是&#xff0c;宁要国内清北复交&#xff0c;也不要海归留学。学历到底重不重要&#x…