网站用ps下拉效果怎么做的,装饰设计师培训,vue.js做的网站,祝贺公司网站上线Redis 设计了简单动态字符串#xff08;Simple Dynamic String#xff0c;SDS#xff09;的结构#xff0c;用来表示 字符串。相比于 C 语言中的字符串实现#xff0c;SDS 这种字符串的实现方式#xff0c;会提升字符串的操 作效率#xff0c;并且可以用来保存二进制数据… Redis 设计了简单动态字符串Simple Dynamic StringSDS的结构用来表示 字符串。相比于 C 语言中的字符串实现SDS 这种字符串的实现方式会提升字符串的操 作效率并且可以用来保存二进制数据。
为什么 Redis 不用 char*
首先得先了解char* 字符串数组的结构特点还有 Redis对字符串的需求是什么所以下面我们就来具体分析一下
char* 的结构设计
char*字符数组的结构很简单就是一块连续的内存空间依次存放了字符串中的每一个 字符。比如下图显示的就是字符串“redis”的char*数组结构。、 从图中可以看到字符数组的最后一个字符是“\0”这个字符的作用是什么呢其实C 语言在对字符串进行操作时char* 指针只是指向字符数组的起始位置而字符数组的结尾 位置就用“\0”表示意思是指字符串的结束
c语言标准库呢就是检查字符这个字符是不是\0然后不是加一往下走是的话结束
创建了两个字串变量 a 和 b分别给它们赋值为“red\0is”和“redis\0”。然后我用 strlen 函数 计算这两个字符串长度如下所示 当程序执行完这段代码后输出的结果分别是 3 和 5。
也就是说char* 字符串以“\0”表示字符串的结束其实会给我们保存数据带来一定的负 面影响。如果我们要保存的数据中本身就有“\0”那么数据在“\0”处就会被截断 而这就不符合 Redis 希望能保存任意二进制数据的需求了
操作函数复杂度
用char* 会导致复杂度增加
字符串追加函数 strcat 和上边的strlen函数都需要遍历到字符串的末尾 SDS 的设计思想
因为 Redis 是使用 C 语言开发的所以为了保证能尽量复用 C 标准库中的字符串操作函 数Redis 保留了使用字符数组来保存实际的数据。但是和 C 语言仅用字符数组不同 Redis 还专门设计了 SDS即简单动态字符串的数据结构
SDS 结构设计
首先SDS 结构里包含了一个字符数组 buf[]用来保存实际数据。同时SDS 结构里还 包含了三个元数据分别是字符数组现有长度 len、分配给字符数组的空间长度 alloc以 及 SDS 类型 flags。其中Redis 给 len 和 alloc 这两个元数据定义了多种数据类型进 而可以用来表示不同类型的 SDS 在 Redis 源码中查找过 SDS 的定义那你可能会看到Redis 使用 typedef 给 char* 类型定义了一个别名这个别名就是 sds
typedef char *sds;
因为 SDS 本质还是字符数组只是在字符数组基础上增加了额外的元数据。在 Redis 中需要用到字符数组时就直接使用 sds 这个别名。
在创建新的字符串时Redis 会调用 SDS 创建函数 sdsnewlen。sdsnewlen 函数 会新建 sds 类型变量也就是 char* 类型变量并新建 SDS 结构体把 SDS 结构体中
的数组 buf[] 赋给 sds 类型变量。最后sdsnewlen 函数会把要创建的字符串拷贝给 sds 变量。下面的代码就显示了 sdsnewlen 函数的这个操作逻辑你可以看下 SDS操作效率
因为它本身的数据结构
紧凑型字符串结构的编程技巧
SDS 结构中有一个元数据 flags表示的是 SDS 类型
事实上SDS 一共设计了 5 种类型分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64
这 5种类型的主要区别就在于它们数据结构中的字符数组现有长度 len 和分配空间长度 alloc这两个元数据的数据类型不同。
因为 sdshdr5 这一类型 Redis 已经不再使用了主要来了解下剩余的 4 种类 型。以 sdshdr8 为例它的定义如下所示 我们可以看到现有长度 len 和已分配空间 alloc 的数据类型都是 uint8_t。uint8_t 是 8 位无符号整型会占用 1 字节的内存空间。当字符串类型是 sdshdr8 时它能表示的字符 数组长度包括数组最后一位\0不会超过 256 字节2 的 8 次方等于 256。
而对于 sdshdr16、sdshdr32、sdshdr64 三种类型来说它们的 len 和 alloc 数据类型分 别是 uint16_t、uint32_t、uint64_t即它们能表示的字符数组长度分别不超过 2 的 16 次方、32 次方和 64 次方。这两个元数据占用的内存空间在 sdshdr16、sdshdr32、 sdshdr64 类型中则分别是 2 字节、4 字节和 8 字节。
SDS 之所以设计不同的结构头即不同类型是为了能灵活保存不同大小的字 符串从而有效节省内存空间
除了设计不同类型的结构头Redis 在编程上还使用了专门的编译优化来节省内存 空间。在刚才介绍的 sdshdr8 结构定义中我们可以看到在 struct 和 sdshdr8 之间使 用了__attribute__ ((__packed__))如下所示
struct __attribute__ ((__packed__)) sdshdr8
其实这里__attribute__ ((__packed__))的作用就是告诉编译器在编译 sdshdr8 结构时不要使用字节对齐的方式而是采用紧凑的方式分配内存。这是因为在 默认情况下编译器会按照 8 字节对齐的方式给变量分配内存。也就是说即使一个变 量的大小不到 8 个字节编译器也会给它分配 8 个字节
到这里呢需要了解一下字节对齐是为什么