REDIS17_源码分类、SDS底层原理说明、INT编码格式、EMBSTR编码格式、RAW编码格式
创始人
2025-05-28 19:53:10
0

文章目录

  • ①. C语言源代码的核心部分
  • ②. KV键值对到底是什么
  • ③. 从set hello world说起
  • ④. String - 3大编码格式
  • ⑤. String - 重新设置SDS
  • ⑥. 三大编码 - INT编码格式
  • ⑦. 三大编码 - EMBSTR编码格式
  • ⑧. 三大编码 - RAW编码格式

①. C语言源代码的核心部分

  • ①. git源码地址:git clone https://github.com/redis/redis.git (redis-6.0.8\redis-6.0.8\src)
    在这里插入图片描述在这里插入图片描述

  • ②. Redis基本的数据结构(骨架)

  1. 简单动态字符串sds.c
  2. 整数集合intset.c
  3. 压缩列表ziplist.c
  4. 快速链表quicklist.c
  5. 字典dict.c
  6. Streams的底层实现结构listpack.c和rax.c(了解)
  • ③. Redis数据类型的底层实现
  1. Redis对象object.c
  2. 字符串t_string.c
  3. 列表t_list.c
  4. 字典t_hash.c
  5. 集合及有序集合t_set.c和t_zset.c
  6. 数据流t_stream.c
  • ④. Redis数据库的实现
  1. 数据库的底层实现db.c
  2. 持久化rdb.c和aof.c
  • ⑤. Redis服务端和客户端实现
  1. 事件驱动ae.c和ae_epoll.c
  2. 网络连接anet.c和networking.c
  3. 服务端程序server.c
  4. 客户端程序redis-cli.c
  • ⑥. 其他
  1. 主从复制replication.c
  2. 哨兵sentinel.c
  3. 集群cluster.c
  4. 其他数据结构,如hyperloglog.c、geo.c等
  5. 其他功能,如pub/sub、Lua脚本

②. KV键值对到底是什么

  • ①. 总结语:redis是key-value存储系统,其中key类型一般为字符串, value类型则为redis对象(redisObject)
    在这里插入图片描述

  • ②. 6大类型说明(粗分)

  1. 传统的5大类型
  2. 新介绍的3大类型(bitmap、hyperLogLog:实质String | GEO:实质Zset)
    在这里插入图片描述
  • ③. 图解

在这里插入图片描述

  • ④. C语言struct结构体语法简介
    在这里插入图片描述在这里插入图片描述

  • ⑤. 字典、KV是什么:每个键值对都会有一个dictEntry
    在这里插入图片描述在这里插入图片描述

  • ⑥. redisObject +Redis数据类型+Redis 所有编码方式(底层实现)三者之间的关系
    在这里插入图片描述

③. 从set hello world说起

  • ①. set hello word为例,因为Redis是KV键值对的数据库,每个键值对都会有一个dictEntry(源码位置:dict.h)
  1. 里面指向了key和value的指针,next指向下一个dictEntry
  2. key是字符串,但是Redis没有直接使用C的字符数组,而是存储在redis自定义的SDS中
  3. value既不是直接作为字符串存储,也不是直接存储在SDS中,而是存储在redisObject中
  4. 实际上五种常用的数据类型的任何一种,都是通过redisObject来存储的
    在这里插入图片描述
  • ②. redis看看类型:type key | 看看编码:object encoding hello | debug结构:debug object person
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> type hello 
string
127.0.0.1:6379> object encoding hello 
"embstr"
127.0.0.1:6379> debug object hello 
Value at:0x7fa41f80e3a0 refcount:1 encoding:embstr serializedlength:6 lru:891806 lru_seconds_idle:61
127.0.0.1:6379> 
  • ③. 为了便于操作,Redis采用redisObjec结构来统一五种不同的数据类型,这样所有的数据类型就都可以以相同的形式在函数间传递而不用使用特定的类型结构。同时,为了识别不同的数据类型, redisObjec中定义了type和encoding字段对不同的数据类型加以区别。简单地说,redisObjec就是string、hash、list、set、zset的父类 ,可以在函数间传递时隐藏具体的类型信息,所以作者抽象了redisObjec结构来到达同样的目的
struct redisObject {/*对象的类型,包括:OBJECT_STRING、OBJECT_LIST、OBJECT_HASH、OBJECT_SET、OBJECT_ZSET */unsigned type:4;/*具体的数据结构*/ unsigned encoding:4;/*24位,对象最后一次被命令程序访问的时间,与内存回收有关*/unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or* LFU data (least significant 8 bits frequency* and most significant 16 bits access time). *//*引用计数,当refcount=0的时候,表示该对象已经不被任何对象引用,则可以进行垃圾回收了*/int refcount;/*指向对象实际的数据结构*/void *ptr;
};

在这里插入图片描述

  • ④. RedisObject各字段的含义
  1. 4位的type表示具体的数据类型
  2. 4位的encoding表示该类型的物理编码方式见下表,同一种数据类型可能有不同的编码方式((比如String就提供了3种:int embstr raw))
  3. lru字段表示当内存超限时采用LRU算法清除内存中的对象
  4. refcount表示对象的引用计数
  5. ptr指针指向真正的底层数据结构的指针
    在这里插入图片描述

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

④. String - 3大编码格式

  • ①. int
  1. 保存long型(长整型)的64位(8个字节)有符号整数
  2. 9223372036854775807
  3. 上面数字最多19位
  4. 只有整数才会使用 int,如果是浮点数, Redis 内部其实先将浮点数转化为字符串值,然后再保存
    在这里插入图片描述
    在这里插入图片描述
  • ②. embstr:代表embstr格式的SDS(Simple Dynamic String 简单动态字符串),保存长度小于44字节的字符串。EMBSTR顾名思义即:embedded string,表示嵌入式的String

  • ③. raw:保存长度大于44字节的字符串

⑤. String - 重新设置SDS

  • ①. C语言中字符串展示
    在这里插入图片描述

  • ②. Redis没有直接复用C语言的字符串,而是新建了属于自己的结构-----SDS
    在Redis数据库里,包含字符串值的键值对都是由SDS实现的(Redis中所有的键都是由字符串对象实现的即底层是由SDS实现,Redis中所有的值对象中包含的字符串对象底层也是由SDS实现)

    在这里插入图片描述

  • ③. Redis为什么重新设计一个SDS数据结构?
    谈谈自己对内存重新分配理解:比如现在有一个set key1 value1 使用的是sds8进行存储,这个时候重新set key1 value(没有超过1个bite),那么就会继续延用以前的,如果大于了1个bite,那么就会重新分配比如分配到sds16
    在这里插入图片描述

  • ④. len:记录buf数组中已使用字节数量
    flags:当前类型(不同的sdshdr)
    alloc:不包括头和空结束符的字节数量

typedef **char** *sds;
struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];};struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];};struct __attribute__ ((__packed__)) sdshdr64 {
static inline char sdsReqType(size_t string_size) {if (string_size < 32)  return SDS_TYPE_5;if (string_size < 0xff) //2^8 -1  return SDS_TYPE_8;if (string_size < 0xffff) // 2^16 -1  return SDS_TYPE_16;if (string_size < 0xffffffff)  // 2^32 -1 return SDS_TYPE_32;return SDS_TYPE_64;
}

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

  • ⑤. set k1 v1底层发生了什么?调用关系
    在这里插入图片描述在这里插入图片描述

⑥. 三大编码 - INT编码格式

  • ①. 我们先来瞅一瞅三大编码长什么样?
    在这里插入图片描述

  • ②. 当字符串键值的内容可以用一个64位有符号整形来表示时,Redis会将键值转化为long型来进行存储,此时即对应 OBJ_ENCODING_INT 编码类型。内部的内存结构表示如下:
    命令示例: set k1 123
    在这里插入图片描述

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

set k1 123
set k2 123

在这里插入图片描述

  • ④. redis源代码:object.c
    在这里插入图片描述在这里插入图片描述

⑦. 三大编码 - EMBSTR编码格式

  • ①. redis源代码:object.c
    在这里插入图片描述
  • ②. 对于长度小于44的字符串,Redis对键值采用OBJ_ENCODING_EMBSTR方式,EMBSTR顾名思义即:embedded string,表示嵌入式的String。从内存结构上来讲即字符串sds结构体与其对应的 redisObject对象分配在同一块连续的内存空间,字符串sds嵌入在redisObject对象之中一样
    在这里插入图片描述
    在这里插入图片描述
  • ③. redis源代码:object.c(embStr不会重新再次开辟空间,而是会嵌入在redisObject里面)
    在这里插入图片描述
    在这里插入图片描述

⑧. 三大编码 - RAW编码格式

  • ①. 先来瞅一瞅源码
    在这里插入图片描述

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

  • ③. 明明没有超过阈值,为什么变成raw了
    在这里插入图片描述

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

  • ⑤. embstr与raw类型底层的数据结构其实都是SDS(简单动态字符串,Redis内部定义sdshdr一种结构)
    在这里插入图片描述在这里插入图片描述

相关内容

热门资讯

扫房神器2安卓系统,打造洁净家... 你有没有发现,家里的灰尘就像小精灵一样,总是悄悄地在你不注意的时候跳出来?别急,今天我要给你介绍一个...
安卓完整的系统设置,全面掌控手... 亲爱的手机控们,是不是觉得你的安卓手机用久了,功能越来越强大,但设置却越来越复杂?别急,今天就来带你...
电视安卓系统是几代机子,揭秘新... 你有没有想过,家里的电视是不是已经升级到了最新的安卓系统呢?别小看了这个小小的系统升级,它可是能让你...
安卓系统隐私有经常去,系统级防... 你知道吗?在咱们这个数字化时代,手机可是我们生活中不可或缺的好伙伴。但是,你知道吗?这个好伙伴有时候...
安卓10系统断网软件,轻松实现... 你有没有遇到过这种情况?手机突然断网了,明明信号满格,却连不上网,急得你团团转。别急,今天就来给你揭...
安卓可以改什么系统版本,体验全... 你有没有想过,你的安卓手机其实可以像换衣服一样,换一个全新的“系统版本”呢?没错,这就是今天我们要聊...
最好的平板游戏安卓系统,畅享指... 亲爱的游戏迷们,你是否在寻找一款能够让你在安卓平板上畅玩无忧的游戏神器?别急,今天我就要给你揭秘,究...
华为安卓系统卡顿解决,华为安卓... 你是不是也遇到了华为安卓系统卡顿的问题?别急,今天就来给你支几招,让你的华为手机重新焕发活力!一、清...
安卓建议升级鸿蒙系统吗,探讨鸿... 亲爱的安卓用户们,最近是不是被鸿蒙系统的新鲜劲儿给吸引了?是不是在犹豫要不要把你的安卓手机升级成鸿蒙...
安卓如何变苹果系统桌面,桌面系... 你有没有想过,把你的安卓手机变成苹果系统桌面,是不是瞬间高大上了呢?想象那流畅的动画效果,那简洁的界...
windows平板安卓系统升级... 你有没有发现,最近你的Windows平板电脑突然变得有些不一样了?没错,就是那个一直默默陪伴你的小家...
安卓系统扩大运行内存,解锁更大... 你知道吗?在科技飞速发展的今天,手机已经成为了我们生活中不可或缺的好伙伴。而手机中,安卓系统更是以其...
安卓系统怎么改变zenly,探... 你有没有发现,你的安卓手机上的Zenly应用最近好像变得不一样了?没错,安卓系统的大手笔更新,让Ze...
英特尔安卓子系统,引领高效移动... 你有没有想过,手机里的安卓系统竟然也能和电脑上的英特尔处理器完美结合呢?这可不是天方夜谭,而是科技发...
永远会用安卓系统的手机,探索安... 亲爱的手机控们,你是否也有那么一款手机,它陪伴你度过了无数个日夜,成为了你生活中不可或缺的一部分?没...
有哪些安卓手机系统好用,好用系... 你有没有发现,现在手机市场上安卓手机的品牌和型号真是琳琅满目,让人挑花了眼?不过别急,今天我就来给你...
卡片记账安卓系统有吗,便捷财务... 你有没有想过,用手机记账是不是比拿着小本本记录来得方便多了?现在,手机上的应用层出不穷,那么,有没有...
武汉摩尔影城安卓系统APP,便... 你有没有想过,一部手机就能带你走进电影的世界,享受大屏幕带来的震撼?今天,就让我带你详细了解武汉摩尔...
联想刷安卓p系统,畅享智能新体... 你有没有发现,最近联想的安卓P系统刷机热潮可是席卷了整个互联网圈呢!这不,我就迫不及待地来和你聊聊这...
mac从安卓系统改成双系统,双... 你有没有想过,你的Mac电脑从安卓系统改成双系统后,生活会有哪些翻天覆地的变化呢?想象一边是流畅的苹...