Redis底层存储结构一---Redis中Key-Value中的Key

简介:
首先我们直到Redis的数据存储是以Key-Value的形式来存储的,这个和我们Java中的map很类似,这篇博客我们就来讲一讲Redis的Key-Value存值形式的Key。
其实Redis中所有的Key都是一种字符串的形式,就比如说下图所示,我们无论怎么去设置它的Key,虽然我们看起来有整型值或者浮点值等等,在Redis的服务端全部都存储的字符串类型:

在这里插入图片描述

然而,我们知道Redis的底层是C语言写的,C语言表示一个字符串是用字符数组来表示的,但是直接用C语言的字符数组来表示的话,会出现很多问题,所以Redis搞出来了一个SDS的字符串,类似与我么java搞出来的String,这个会出现什么问题呢,具体在为什么要搞出这个SDS的地方来说。
接下来我们就来详细介绍一下SDS:

1、什么是SDS?

SDS 全程是 simple dynamic string (简单的动态字符串),是 Redis 提供的一个存储字符串的变量类型。

2、为什么要用SDS?

有人会说,Redis的底层是以C语言来写的,C语言也可以表示字符串,可以使用字符数组,但是为什么Redis不直接C语言的字符数组呢,而需要自己定义一个 SDS 的变量类型来存储呢,我想原因可能是这样的:
原因:首先 Redis 是一个中间件,它对接的语言有很多,比如Java,C#,Go,PHP语言,它接收到的数据请求也不一定规范,都是从客户端发过来的,可能是以流(字节流)或者其它形式发过来的。

3、SDS的三大特性

3.1、二进制安全的数据结构

Redis是以(key-value)形式存数据的一个数据库,底层开发语言是C语言,Redis在存储数据时,所有的key都是以字符串的形式存储的,我们的C语言表示一个字符串是以下面的形式表示的,一个字符数组,如下代码所示:

// C语言在默认读取这个字符串时,字符串后面应该还有个结尾符,\0
char str[] = "ale";

那么问题就来了,如果传入的这个key或者Value本身中间就有\0呢,那么这个时候直接就用C语言的字符数组去截取的话,就会丢失掉\0后面的数据。
所以,SDS就有一个len属性,一个buffer属性,len表示字符长度,buffer存储数据。

sds:
	len: 8 
	char buf[] = "ale\0lele"

3.2、提供了内存的预分配机制,避免了频繁的内存分配

为什么说SDS是动态的字符串呢,请看下面:

sds:
	free: 2
	len: 8 
	char buf[] = "ale\0lele"

按照上面这个字符串来说呢,现在这个字符串的总长度为10,用了8个字节,现在空闲空间还剩两个字节。如果说我现在要把这个字符串改变为 ale\0lele123 ,这就是11个字节,相当于在原有的基础上增加了3个字节,但是由于只剩下两个字节的空闲空间了,所以说不够,这个时候 SDS 会有自己的扩容机制,会先new一个新字符串长度的2倍的空间,然后再将需要赋值的字符串赋值进去,这个时候新字符串就变成了下面这个样子。

sds:
	free: 9
	len: 11 
	char buf[] = "ale\0lele123"

如果再次需要赋值 ale\0lele123456 ,需要增加3个字节,发现原先的剩余空间还有9个字节,够用,直接赋值即可。
注意:当len的长度大于1M之后,也就是1024 * 1024,扩容机制将不会是原来的2倍,而是每次在新的字符串长度上增加1M。

3.3、兼容C语言的函数库

为什么会说兼容了C语言的函数库呢,因为SDS在获取到值之后,会自动往字符串的最后面加上\0,所以格式就和C语言的字符串格式就一致了,就兼容了C语言的函数库。

4、SDS在各个版本的数据结构

4.1、SDS在3.2之前的样子(包含3.2)

Redis3.2版本之前的数据结构大体就是如下所示:

sds:
	len: 8 
	char buf[] = "ale\0lele"

4.2、SDS在3.2之后的样子

数据结构产生变化的原因:通常情况下,SDS中的len和free会占4个字节,但是我们的真实数据中一般的数据也就几百个字节,4个字节,232可以表示42亿多的数据,很显然,这样表示的话很浪费资源。
改变:3.2之后,我们根据字符串的长度,新增加了更多的表示方法。
如下图所示:
alloc - len就是我们上面说的free
每一个长度的字串alloc和len所占的长度都不一样,

类型长度
char1个字节,8个bit位
uint8_t1个字节,8个bit位
uint16_t2个字节,16个bit位
uint32_t3个字节,32个bit位
uint64_t4个字节,64个bit位

在这里插入图片描述

5、Redis服务端如何区分该字符串用哪一个数据结构

当我们在客户端给Redis传入一个字符串,Redis是如何知道它用哪个数据结构来存储吗,其实都是在这个flag上面体现的,在4.2中我们可以看到3.2之后就增加了这个flags标识位,flags中有一个type,用3个bit位表示,来区分用哪个数据结构,flags的图示如下:

在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值