Redis系列-13.Redis经典五大类型源码及底层实现(一)(中)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis系列-13.Redis经典五大类型源码及底层实现(一)

Redis系列-13.Redis经典五大类型源码及底层实现(一)(上):https://developer.aliyun.com/article/1414742


五大经典结构解析


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

Debug Object key

开启后

Value at: 内存地址


refcount: 引用次数


encoding: 物理编码类型


serializedlength: 序列化后的长度(注意这里的长度是序列化后的长度,保存为rdb文件时使用了该算法,不是真正存贮在内存的大小),会对字串做一些可能的压缩以便底层优化


lru:记录最近使用时间戳


lru_seconds_idle:空闲时间


String数据类型介绍


3大物理编码方式


RedisObjectt内部对应的3大物理编码

int


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

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


embstr


代表embstr格式的SDS 简单动态字符串,保存长度小于44字节的字符串,顾名思义,表示嵌入式的String


raw


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


3大物理编码案例

假如现在展现一个字符串:Redis

Redis没有直接复用C语言的字符串,而是新建了属于自己的结构-----SDS


在Redis数据库里,包含字符串值的键值对都是由SDS实现的(Redis中所有的键都是由字符串对象实现的即底层是由SDS实现,Redis中所有的值对象中包含的字符串对象底层也是由SDS实现)。

SDS简单动态字符串


sds.h源码分析

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


sdshdr5、(2^5=32byte)


sdshdr8、(2 ^ 8=256byte)


sdshdr16、(2 ^ 16=65536byte=64KB)


sdshdr32、 (2 ^ 32byte=4GB)


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


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


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


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

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


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

C语言 SDS
字符串长度处理 需要从头开始遍历,直到遇到 ‘\0’ 为止,时间复杂度O(N) 记录当前字符串的长度,直接读取即可,时间复杂度 O(1)

内存重新分配

分配内存空间超过后,会导致数组下标越级或者内存分配溢出

空间预分配 SDS 修改后,len 长度小于 1M,那么将会额外分配与 len 相同长度的未使用空间。如果修改后长度大于 1M,那么将分配1M的使用空间。惰性空间释放 有空间分配对应的就有空间释放。SDS 缩短时并不会回收多余的内存空间,而是使用 free 字段将多出来的空间记录下来。如果后续有变更操作,直接使用 free 中记录的空间,减少了内存的分配。

二进制安全

二进制数据并不是规则的字符串格式,可能会包含一些特殊的字符,比如 ‘\0’ 等。前面提到过,C中字符串遇到 ‘\0’ 会结束,那 ‘\0’ 之后的数据就读取不上了 根据 len 长度来判断字符串结束的,二进制安全的问题就解决了

源码分析


set k1 v1 底层发生了什么?调用关系

三大物理编码方式

int编码

set k1 123


命令示例: set k1 123


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

Redis 启动时会预先建立 10000 个分别存储 0~9999 的 redisObject 变量作为共享对象,这就意味着如果 set字符串的键值在 0~10000 之间的话,则可以


直接指向共享对象 而不需要再建立新对象,此时键值不占空间!


set k1 123


set k2 123


接下来就很类似Integer,如果是128以内的话,那么常量池中就存在

redis源代码:server.h,笔记下面还有

redis6源代码:object.c笔记下面还有

redis7源代码:object.c笔记下面还有

EMBSTR编码格式

set k1 abc


redis源代码:object.c

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

进一步createEmbeddedStringObject方法


redis源代码:object.c


从图中也可以看出,内存相当紧凑,没有重新分配空间

RAW编码格式

set k1 大于44长度的一个字符串,随便写

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

明明没有超过阈值,为什么变成raw了?

判断不出来,就取最大Raw


转变逻辑图


Redis系列-13.Redis经典五大类型源码及底层实现(一)(下):https://developer.aliyun.com/article/1414746


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
17天前
|
XML JSON NoSQL
Redis的常用数据结构之字符串类型
Redis的常用数据结构之字符串类型
19 0
|
29天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
47 0
|
9天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
151 10
|
29天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
31 0
|
1月前
|
存储 NoSQL 网络协议
读懂Redis源码,我总结了这7点心得
读懂Redis源码,我总结了这7点心得
|
3月前
|
存储 NoSQL 关系型数据库
Redis Sorted Set 底层实现原理深度解读与排行榜实战
Redis Sorted Set 底层实现原理深度解读与排行榜实战
59 0
|
3月前
|
缓存 NoSQL 关系型数据库
Redis 7.0 源码调试环境搭建与源码导读技巧
Redis 7.0 源码调试环境搭建与源码导读技巧
54 0
|
3月前
|
存储 NoSQL Java
面试题:redis除了使用string、set还了解哪些类型
面试题:redis除了使用string、set还了解哪些类型
15 0
|
3月前
|
存储 NoSQL 算法
redis存储什么类型的数据?redis分布式锁怎么实现的?
redis存储什么类型的数据?redis分布式锁怎么实现的?
|
3月前
|
NoSQL 算法 Redis
redis7.0源码阅读(五):跳表(skiplist)
redis7.0源码阅读(五):跳表(skiplist)
62 1

热门文章

最新文章