1、Redis 动态字符串简介

cmatrix
在 Redis 中,字符串是最常用的数据结构之一,而 Redis 中的字符串使用的是简单动态字符串(Simple Dynamic String)。简单动态字符串是 Redis 中实现字符串的基础,同时也是其他数据结构的实现基础之一。

redis 动态字符串 底层存储
简单动态字符串是一个可以动态调整长度的字符数组,同时支持字符串的常见操作,如追加、删除、修改等。它遵循 C 字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在 SDS 的`len`属性里面,并且为空字符分配额外的1字节空间,以及添加空字符到字符串末尾等操作都是由 SDS 函数自动完成的,所以这个空字符对于 SDS 的使用者来说是完全透明的。
2、Redis 动态字符串 使用场景

无处不在的字符串
Redis 动态字符串可以应用于存储键值对、验证码、缓存功能、计数器、bitmap 位图等场景。
以存储验证码为例,在网站进行登录、注册、获取验证码等操作时,通常会接收到一些验证码,并提示在一定时间后失效。可以使用以下命令存储验证码:
set phone_num code ex 600
其中`phone_num`为手机号,`code`为验证码,`ex 600`表示超时时间为600秒。当用户输入验证码并提交时,后台可以先使用`get phone_num`获取验证码,然后将其与数据库中存储的值进行比较,从而完成身份验证。
3、C语言 手撕动态字符串

简单SDS demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int len; //当前字符串长度
int free; //剩余未使用长度
char buf[]; //字符串首地址
} sdshdr;
//创建动态字符串
sdshdr *sdscat(sdshdr *s, const char *t) {
int tlen = strlen(t);
s = realloc(s, sizeof(sdshdr) + s->len + tlen + 1);
if (s == NULL) {
printf("Memory reallocation failed.\n");
exit(1);
}
memcpy(s->buf + s->len, t, tlen);
s->len += tlen;
s->free = s->free - tlen;
s->buf[s->len] = '\0';
return s;
}
//初始化动态字符串
sdshdr *sdsnew(const char *init) {
int initlen = (init == NULL) ? 0 : strlen(init);
sdshdr *s = malloc(sizeof(sdshdr) + initlen + 1);
if (s == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
s->len = initlen;
s->free = 0;
if (initlen) memcpy(s->buf, init, initlen);
s->buf[initlen] = '\0';
return s;
}
int main() {
char data[] = "This is a dynamic string.";
sdshdr *s = sdsnew(data); //创建动态字符串
printf("%s, length: %d, free: %d\n", s->buf, s->len, s->free); //输出动态字符串内容、长度和空余内存大小
s = sdscat(s, " I want to add more content to it!"); //追加内容
printf("%s, length: %d, free: %d\n", s->buf, s->len, s->free); //再次输出动态字符串内容、长度和空余内存大小
free(s); //释放内存
return 0;
}

运行结果
这个示例程序中,我们定义了一个结构体sdshdr,用于存储动态字符串的信息,其中包括当前字符串长度len、未使用的内存空间free和字符串首地址buf。我们使用了sdsnew函数来创建一个动态字符串,并使用sdscat函数向字符串中追加内容。
由于动态字符串是通过realloc函数实现动态内存分配的,所以在每一次增加字符串长度时需要重新分配内存空间。为了提高效率,在重新分配内存时,我们可以一次性分配比实际需要更大的内存,以避免频繁的内存分配和复制,提高程序运行效率。
注意,在使用完成动态字符串后,要及时释放内存,以避免内存泄露。
附件 realloc函数说明

realloc
其中,ptr是已分配内存的指针,size是新的内存空间大小。调用realloc函数时,它会将ptr所指向的已分配的内存空间重新调整大小为size,并返回一个指向调整后内存空间首地址的指针。
realloc函数返回的指针可能与ptr相同,也可能是新分配的内存空间的首地址。如果调整失败,realloc函数会返回一个空指针NULL。
使用realloc函数时需要注意以下几点:
1.如果ptr为NULL,则相当于调用malloc函数,用于分配一块新的内存空间。
2.如果size为0,则相当于调用free函数,用于释放已分配的内存空间。
3.如果size大于原指针所指内存空间的大小,则新分配的内存空间中未初始化的部分是未定义的,应该使用memset函数手动初始化。
4.如果size小于原指针所指内存空间的大小,则可能造成数据丢失,应该备份原内存数据后进行分配。

add oil




