0%

字符串实现

字符串实现

redis中的字符串是一个可以修改的字符串,在内存中以字节数组的形式存在。如果不进行封装的话是使用strlen标准库函数来进行获取长度,该函数的算法复杂度是O(n),需要对字节数组进行遍历扫描,而redis是单线程的,这种程度的结构无法承受。redis封装了一个新的字符串结构SDS,结构是一个带长度信息的字节数组

源码结构

sds.h其内部使用的是SDS简单动态字符串,保存了长度信息,获取字符串长度只需要O(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
struct __attribute__ ((__packed__)) sdshdr5 {
// 存储了字符串的类型和长度,3位存类型,5位存长度
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
// 暂时应该是没有用到5的,只用到了8、16、32、64
struct __attribute__ ((__packed__)) sdshdr8 {
// header中进行存储len、alloc、flags
// 当前使用空间大小,即字符串的长度
uint8_t len; /* used */
// 去掉header和结尾空字符后的buf的总长度,就是已经分配空间的长度
uint8_t alloc; /* excluding the header and null terminator */
// 8位的标记,3位存类型,5位没有使用
unsigned char flags; /* 3 lsb of type, 5 unused bits */
// 数组进行存储
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len; /* used */
uint16_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len; /* used */
uint64_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};

编码格式

编码 对象
OBJ_ENCODING_INT 使用整数值实现的字符串对象
OBJ_ENCODING_EMBSTR 使用embstr编码的简单动态字符串实现的字符串对象
OBJ_ENCODING_RAW 使用简单动态字符串实现的字符串对象

string有三种编码格式

  • int 整数值

  • embstr 用于存储短字符串的编码方式,字符串长度小于等于44字节使用,数据保存在一块连续的内存里

  • raw 字符串值长度大于44字节使用

embstr和raw两种编码的区别

embstr编码用于保存短字符串,与raw编码一样,都是使用redisObject结构和sdshdr结构来表示字符串对象,但是raw编码会调用两次内存分配函数来分别创建redisObject结构和sdshdr结构,两个对象在内存地址上是不连续的;而embstr编码则通过调用一次内存分配函数来分配一块连续的内存空间,空间中依次包含redisObject和sdshdr两个结构

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10