我们都知道Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。

不过Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题:

获取字符串长度的需要通过运算非二进制安全不可修改 Redis构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS

SDS 的结构:

SDS 是 Redis 用于表示字符串的底层数据结构。它的结构由以下部分组成:

buf:存储字符串内容的区域,是一个字节数组,用于保存实际的字符串数据。alloc: 已经申请的区域的长度len:记录字符串的长度,即 buf 中实际存储的字符数,不包括末尾的空字符 \0。

struct __attribute__((__packed__)) sdshdr8 {

uint8_t len; /*buf 中已经报错的字符串字节数,不含结束标识*/

uint8_t alloc;/*buf 中申请的总字节数,不含结束标识*/

unsigned char flags;/*SDS的头类型,用来控制头部大小*/

char buf [];

}

/*头类型*/

#define SDS_TYPE_5 0

#define SDS_TYPE_8 1

#define SDS_TYPE_16 2

#define SDS_TYPE_32 3

#define SDS_TYPE_64 4

SDS的特性和优势:

获取字符串长度的时间复杂度为O(1)动态扩容:SDS 允许字符串长度的动态增长,并且能够动态地调整内存空间,以避免频繁的内存分配和复制操作,提高了性能。二进制安全:SDS 可以存储任意二进制数据,不受空字符 \0 的限制,因此可以存储图片、压缩数据等任意类型的数据。预分配和惰性空间释放:SDS 采用预分配的策略,提前分配一定的空间以减少频繁的内存分配操作。同时,它使用惰性空间释放策略,在缩短字符串长度时并不立即释放多余的空间,而是保留一定的额外空间,以备后续可能的扩展使用。修改时复制(Copy on Write):SDS 在进行修改操作时,会先进行复制,以确保修改操作不会影响到其他引用该字符串的地方,保证数据的安全性。

动态扩容过程

假如我们要给"test"追加一个"ordersheet"

首先,需要计算追加的字符串长度,即 “ordersheet” 的长度为 10。SDS 检查当前剩余的空间是否能容纳新的字符串,发现空间不够以容纳所有字符。触发扩容操作,按照一定规则申请新的内存空间将原始的字符串 “test” 复制到新的更大空间,并在末尾追加 “ordersheet\0”。更新字符串的长度为 14(“test” 的长度 4 + “ordersheet” 的长度 10)。调整空闲空间,确保在将来的操作中有足够的预留空间

申请新内存空间规则:

如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。

SDS 的优势与应用:

高效性能:SDS 通过动态扩容和预分配机制,更高效地处理内存空间,减少了频繁的内存操作,提升了性能。安全性和灵活性:SDS 的二进制安全性保证了可以存储和处理任意类型的数据,而不受到传统 C 字符串的限制。其丰富的操作函数提供了对字符串进行各种操作的灵活性

SDS 的优化技巧

合理使用空间预分配: 在创建 SDS 字符串时,根据实际需求预先分配足够的空间。不要过度分配,但也不要频繁进行小额的扩容操作,这可以减少不必要的内存操作。避免频繁修改大型字符串: 大型 SDS 字符串的修改可能触发大量的内存重新分配和数据复制,这会影响性能。尽量减少对大型 SDS 字符串的频繁修改操作,考虑在实际需要时一次性完成操作。利用惰性空间释放: SDS 采用惰性空间释放策略,在缩短字符串长度时,并不立即释放多余的空间,而是保留一定的额外空间。这个额外空间在之后可能的扩展使用中能够提供更好的性能。选择合适的 API 函数: 在 Redis 的 API 函数中,有许多针对 SDS 字符串的操作函数。选择合适的函数可以减少不必要的复制或内存分配操作,提高效率。避免频繁的字符串连接操作: 避免使用频繁的字符串连接操作,特别是对大量数据进行连接操作,这可能导致大量的内存重新分配和数据复制。利用合并命令和 Pipeline: 如果需要进行大量的字符串操作,可以利用 Redis 的 Pipeline 特性或合并多个操作命令,以减少网络开销和提高性能。内存管理: 在需要释放 SDS 字符串时,确保调用合适的释放函数以释放 SDS 所占用的内存,以免造成内存泄漏。监控和优化: 使用 Redis 提供的监控工具或命令,监视 SDS 字符串的使用情况,并针对性地进行优化调整,比如合理设置过期时间,控制字符串的长度等

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: