三、Redis数据结构-动态字符串SDS(simple dynamic string)
1、Redis前言
C语言的传统的字符串(以’\0’结尾的字符数组)表示。
SDS提升字符串的操作效率,同时也可以保存二进制数据。因为传统C字符串符合ASCII编码,这种编码的操作的特点就是:遇零则止 。即,当读一个字符串时,只要遇到’\0’结尾,就认为到达末尾,就忽略’\0’结尾以后的所有字符。因此,如果传统字符串保存图片,视频等二进制文件,操作文件时就被截断了。举例几个常见命令,直观感受下字符串的操作:
127.0.0.1:6379> set str1 Redis OK 127.0.0.1:6379> get str1 "Redis" 127.0.0.1:6379> type str1 string 127.0.0.1:6379> strlen str1 (integer) 5
详细的相关数据类型的命令操作可以参考查询如下网址:
Redis命令中心(Redis commands) -- Redis中国用户组(CRUG)
2、SDS源码,主要熟悉下sds.c和sds.h文件即可
typedef char *sds; // sds兼容传统C风格字符串 struct __attribute__ ((__packed__)) sdshdr8 { // attribute((packed))作用是取消编译阶段的内存优化对齐功能
uint8_t len; /* used */ // 字符串的长度
uint8_t alloc; /* excluding the header and null terminator */ // buf指针分配空间的大小
unsigned char flags; /* 3 lsb of type, 5 unused bits */ // 该字符串的类型 s[-1]就是sdshdr中flags变量
char buf[]; // sds是指向sdshdr结构buf成员的
SDS内存空间扩容机制:
sds sdsMakeRoomFor(sds s, size_t addlen) { void *sh, *newsh; size_t avail = sdsavail(s); // 剩余容量 size_t len, newlen, reqlen; char type, oldtype = s[-1] & SDS_TYPE_MASK; int hdrlen; /* Return ASAP if there is enough space left. */ if (avail >= addlen) return s; // 长度足够无需扩容 len = sdslen(s); // 字符串长度 sh = (char*)s-sdsHdrSize(oldtype); reqlen = newlen = (len+addlen); // 扩容后的新字符串长度 assert(newlen > len); /* Catch size_t overflow */ if (newlen < SDS_MAX_PREALLOC) // #define SDS_MAX_PREALLOC (1024*1024) 分配内存最大长度为 1MB newlen *= 2; // 扩容翻倍 else newlen += SDS_MAX_PREALLOC; // 加一个最大长度 type = sdsReqType(newlen); .....return s; }
SDS内存空间释放机制:
void sdsclear(sds s) { sdssetlen(s, 0); s[0] = '\0'; } static inline void sdssetlen(sds s, size_t newlen) { // inline关键字仅仅是建议编译器做内联展开处理,而不是强制 unsigned char flags = s[-1]; switch(flags&SDS_TYPE_MASK) { case SDS_TYPE_5: { unsigned char *fp = ((unsigned char*)s)-1; *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); } break; case SDS_TYPE_8: SDS_HDR(8,s)->len = newlen; // 字符串空间变为0 break; case SDS_TYPE_16: SDS_HDR(16,s)->len = newlen; break; .... } }
总结一下:本文主要了解下动态字符串的结构和内存空间的扩容和释放机制。针对具体方法函数的使用,有问题时再详细看下源码这里就不做过多的赘述了。
本文来自博客园,作者:chch213,转载请注明原文链接:https://www.cnblogs.com/chch213/p/16256143.html