Redis为什么要采取SDS结构以及SDS在对象中的应用

一、SDS结构的好处

Sds(simple dynamic string)的结构如下:

这是一个记录Redis字符串的实例,

Free的值为0,说明没有未分配空间,

len的长度为5说明保存了一个长度为5的字符串,

buf属性是一个char类型的数组,数组的前五个字节分别保存了'R'、'e'、'd'、'i'、's'五个字符,而最后一个字节则保存了空字符'\0'。

这样做,相较于c字符串的好处:

  1. 获取字符串长度的时间复杂度为O(1),而c字符串获取长度需要一个个字符遍历,时间复杂度为O(n)
  2. 因为redis需要频繁的对字符串进行增删改,字符串长度经常发生改变,而分配内存空间是一种很复杂的算法,耗时较长,所以SDS采取了一种空间换时间的的策略,在对字符串进行加长的时候,会获取字符串的free来判断指针的指向的内存空间是否足够容纳新的字符串,如果不够,会拓展sds指针指向的内存空间,拓展的策略为:如果len的属性值小于1MB,那free会分配等于len的一个内存空间,举个例子,如果进行修改之后,SDS的len将变成13字节,那么程序也会分配13字节的未使用空间,SDS的buf数组的实际长度将变成13+13+1=27字节(额外的一字节用于保存空字符)。在删减字符串时,不会立即把删掉的空间释放而是预留起来为下一次增加作准备,另一个好处在于可以不用重新分配内存空间。
  3. 因为SDS用字符串长度来判断字符串是否结束,不会因为’/0’忽略后面的字符串,所以可以用来保存特殊格式的二进制,程序不会对其中的数据做任何限制、过滤、或者假设,数据在写入时是什么样的,它被读取时就是什么样。

二、SDS在保存数据时的应用 

在Redis中每个对象都由redisObject结构表示,下面解释一下结构体中每个属性的意思

type表示每个对象的数据类型

在Redis中,有五种数据类型type的值为其中一种:

当我们设置一个键值对的时候

创建的键和值都是字符串对象

但每个类型都使用了至少两中编码的数据结构,我们需要为这个对象选择一个编码,所以需要encoding属性,encoding为适合对应数据类型的数据结构里的其中一种,对应关系如下:

通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一种固定的编码,极大地提升了Redis的灵活性和效率,因为Redis可以根据不同的使用场景来为一个对象设置不同的编码,从而优化对象在某一场景下的效率。

Ptr指向对应数据结构的指针,并且是已经填充数据的数据结构

如果保存的数据是一个整数,并且这个整数可以用long类型来表示,那么会把编码设置为int(浮点数或超过long类型长度的整数根据字节大小用sds或者embstr)。

如果保存的数据大于32字节,那么会使用raw编码,也就是sds数据结构。

如果保存的数据小于等于32字节,redis为了更快的性能,使用了embstr的数据结构,这是一种专门用于保存短字节数据的优化编码方式,使用raw编码会分别创建redisObject和sdshdr结构,也就是用两次内存分配创建了两次结构体,但是embstr会分配一块连续的内存区域来创建redisObject和sdshdr,这两块就是连在一起的,也就是说用embstr将内存分配的次数减少了一次(注:创建的结构体依然是两个)

最后说一下数据编码的转换,如果是int类型的进行增加了字符串,那么int类型都会变成raw。由于redis并没有为embstr编写修改命令,所以所有embstr使用增删改命令之后都会变成raw

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值