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