Redis设计

一、数据结构与对象

        1.SDS

a.SDS的定义

struct sdshdr {
/**
记录buf
数组中已使用字节的数量

等于SDS
所保存字符串的长度
*/
int len;

/**
记录buf
数组中未使用字节的数量
*/
int free;


//字节数组,用于保存字符串
char buf[];
};

SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不 计算在SDS的len属性里面,并且为空字符分配额外的1字节空间,以及 添加空字符到字符串末尾等操作,都是由SDS函数自动完成的,所以这 个空字符对于SDS的使用者来说是完全透明的。遵循空字符结尾这一惯例的好处是,SDS可以直接重用一部分C字符串函数库里面的函数;

例如<stdio.h>中的printf函数

printf("%s", s->buf);

b.SDS与C字符串的区别

字符串长度:

SDS的字符串长度不包含'/0'

而C字符串长度包含

获取字符串长度的复杂度:

SDS字符串的长度记录在了len中,可直接返回len的值,所以时间复杂度为O(1)

而C字符串需要遍历才能获取,时间复杂度为O(N)

杜绝缓冲区溢出:

由于C字符串不记录自身长度,所以再进行一些操作(比如拼接)时,如果没有为字符串预留出足够的空间,就可能出现缓冲区溢出的问题

与C字符串不同,SDS的空间分配策略完全杜绝了发生缓冲区溢出的可能性:当SDS API需要对SDS进行修改时,API会先检查SDS的空间 是否满足修改所需的要求,如果不满足的话,API会自动将SDS的空间 扩展至执行修改所需的大小,然后才执行实际的修改操作,所以使用 SDS既不需要手动修改SDS的空间大小,也不会发生缓冲区溢出

减少修改字符串时带来的内存重分配次数:

Redis作为数据库,经常被用于速度要求严苛、数据被频繁修 改的场合,如果每次修改字符串的长度都需要执行一次内存重分配的 话,那么光是执行内存重分配的时间就会占去修改字符串所用时间的一 大部分,如果这种修改频繁地发生的话,可能还会对性能造成影响。 为了避免C字符串的这种缺陷,SDS通过未使用空间解除了字符串 长度和底层数组长度之间的关联:在SDS中,buf数组的长度不一定就是 字符数量加一,数组里面可以包含未使用的字节,而这些字节的数量就 由SDS的free属性记录

通过未使用空间,SDS实现了空间预分配惰性空间释放两种优化策略。

空间预分配:

当SDS的API对一个 SDS进行修改,并且需要对SDS进行空间扩展的时候,程序不仅会为 SDS分配修改所必须要的空间,还会为SDS分配额外的未使用空间。

其中分为两种情况:

        1.如果对SDS进行修改之后,SDS的长度(也即是len属性的值)将小于1MB,那么程序分配和len属性同样大小的未使用空间,这时SDS len属性的值将和free属性的值相同。

举个例子,如果进行修改之后, SDS的len将变成13字节,那么程序也会分配13字节的未使用空间,SDS 的buf数组的实际长度将变成13+13+1=27字节(额外的一字节用于保存 空字符)

        2.如果对SDS进行修改之后,SDS的长度将大于等于1MB,那么程序 会分配1MB的未使用空间。

举个例子,如果进行修改之后,SDS的len将 变成30MB,那么程序会分配1MB的未使用空间,SDS的buf数组的实际 长度将为30MB+1MB+1byte。 通过空间预分配策略,Redis可以减少连续执行字符串增长操作所 需的内存重分配次数。

在扩展SDS空间之前,SDS API会先检查未使用空间是否足够,如 果足够的话,API就会直接使用未使用空间,而无须执行内存重分配。

通过这种预分配策略,SDS将连续增长N次字符串所需的内存重分 配次数从必定N次降低为最多N次。

惰性空间释放:

惰性空间释放用于优化SDS的字符串缩短操作:当SDS的API需要 缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩短后 多出来的字节,而是使用free属性将这些字节的数量记录起来,并等待 将来使用。

 

        2.链表

        3.字典

        4.跳表

        5.整数集

        6.压缩列表

        7.对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值