redis源码从main开始10中查看了redis的对象类型,本章来看redis的string类型
11 redis对象之string
// 定义redis对象的结构体
#define REDIS_LRU_BITS 24
typedef struct redisObject {
// 对象类型 有五种
// #define REDIS_STRING 0
// #define REDIS_LIST 1
// #define REDIS_SET 2
// #define REDIS_ZSET 3
// #define REDIS_HASH 4
unsigned type:4;
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
int refcount;
void *ptr;
} robj;
/*
* 创建一个新 robj 对象
*/
robj *createObject(int type, void *ptr) {
robj *o = zmalloc(sizeof(*o));
o->type = type;
o->encoding = REDIS_ENCODING_RAW;
o->ptr = ptr;
o->refcount = 1;
/* Set the LRU to the current lruclock (minutes resolution). */
o->lru = LRU_CLOCK();
return o;
}
在redis源码从main开始2中我们讲述了initServer()方法,在初始化redis服务器的时候,创建了大量用于回复的字符串对象
// 例如,创建一个redis对象,类型是REDIS_STRING,这便是常见的字符串类型对象
shared.crlf = createObject(REDIS_STRING, sdsnew("\r\n"));
// 在创建字符串对象的时候我们看到了使用了sdsnew("\r\n"),
// sdsnew返回一个sds, sds是redis的动态字符串的实现,下面我们来看看相关实现
//这是redis声明的别名
typedef char *sds;
// 这是redis保存字符串对象的结构
struct sdshdr {
int len; // 使用了buf多大空间
int free; // 剩余buf空间
char buf[]; // 存放具体数据的空间
};
// 根据给定的初始化字节 创建一个sds
sds sdsnew(const char *init) {
size_t initlen = (init == NULL) ? 0 : strlen(init);
return sdsnewlen(init, initlen);
}
// 根据给定内容和长度,创建sds
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
if (init) {
// zmalloc 不初始化所分配的内存
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
} else {
// zcalloc 将分配的内存全部初始化为 0
sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
}
// 分配失败
if (sh == NULL) return NULL;
// 已使用长度
sh->len = initlen;
// 没有剩余空间
sh->free = 0;
// 有初始化的内容
if (initlen && init)
memcpy(sh->buf, init, initlen);
// 以 \0 结尾
sh->buf[initlen] = '\0';
// 返回buf部分
return (char*)sh->buf;
}
// 可以通过sds取到整个结构体
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
基于版本3.0.0版本,点击下载https://download.redis.io/releases/redis-3.0.0.tar.gz
本文地址,https://www.ccagml.com/?p=407