2.简单动态字符串

2.1 SDS的定义

SDS的结构体:

int len//记录buf数组中已使用字节的数列

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

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

2.2 SDS与C字符串的区别

2.2.1 常数复杂度获取字符串的长度:

C语言字符串获取长度时间复杂度为O(n)

2.2.2 杜绝缓冲区溢出

C字符串不记录自身长度,会造成缓冲区溢出

在对SDS进行修改时,API会检查SDS对空间是否满足修改所需对有求,如果不满足,API会自动将SDS的空间扩展至执行修改所需的大小,然后才执行所需的修改操作

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

1.空间预分配

用于优化SDS字符串增长操作:当一个API对SDS进行修改,并且需要对SDS对空间进行扩展的时候,程序不仅会为SDS分配修改所必须要的空间,还会为SDS分配额外的未使用空间

当SDS的长度小于1MB,程序分配和len属性同样大小的未使用空间

当SDS的长度大于等于1MB,程序会分配1MB的未使用空间。

2.惰性空间释放

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

2.2.4 二进制安全

C字符串只能存储文本数据

Redis不是使用buf来保存字符,而是用它来保存一系列二进制数据

2.2.5 兼容部分C字符串函数

可以重用一部分库定义的函数

3.链表

链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度

链表键、发布与订阅、慢查询、监视器等功能也用到来链表

3.1 链表和链表节点的实现

listnode{

listnode *head;

listNode *tail;

unsigned long len;

void *(*dup)(void *ptr);

void (*free)(void *ptr);

int (*match)(void *ptr, void *key);

}

Redis链表实现特性:

双端:prev指针,获取当前节点的前置节点,next指针,用来获取当前节点的后置节点

无环:表头节点的prev指针和next指针都指向NULL,对链表的访问以NULL为终点

带有表头节点和表尾节点指针:通过list的head指针和tail指针,程序获取链表的表头节点和表尾节点的复杂度为O(1)

带链表长度计数器:程序使用list结构的len属性来对list持有的链表节点进行计数,程序获取链表长度的时间复杂度为O(1)

多态:链表节点使用void*指针来保存节点值,可以通过dup,free,match为节点值设置类型特定函数,所以链表可以用于保存各种不同类型的值

你可能感兴趣的:(2.简单动态字符串)