Redis存储模型
每次在Redis数据库中创建一个键值对时,至少会创建两个对象,一个是键对象,一个是值对象,而Redis中的每个对象都是由 redisObject 结构来表示.redisObject的结构与对象类型、内存编码、内存回收、共享对象都有关系,一个redisObject对象的大小为16字节:4bit+4bit+24bit+4Byte+8Byte=16Byte。
typedef struct redisObject{
unsigned type:4; //对象类型
unsigned encoding:4; //内部编码
unsigned lru: REDIS_LRU_BITS; //记录最后一次被程序访问的时间 lru time (relative to server.lruLock) 计数时钟
int refcount; //引用计数器
void *ptr; //指向底层数据结构的指针
}robj
-
type对象类型:type字段表示对象的数据类型,占据4个bit,当我们执行type object指令时可以查看相应的类型;
-
encoding内部编码类型:encoding表示对象的内部编码,占4个bit。redis支持的各种数据类型,每种至少存在两种内部编码,比如string存在int、embstr、raw三种类型编码,list存在ziplist、linkedlist两种类型编码。每种类型存在多种不同编码的好处在于可以根据不同的使用场景自动切换内部不同的编码来提高效率,大大的提高了灵活性,也做到了解耦用户和底层编码优化。我们可以通过object encoding key命令来查看相应的编码。
-
LRU计时时钟:lru记录的是对象最后一次被命令访问的时间,占据的比特数不同的版本有所不同(如4.0版本占24比特,2.6版本占22比特)。通过计算lru时间和当前时间差值我们可以得到某个对象的空转时间,object idletime key命令可以显示该空转时间(单位是秒)。object idletime命令的一个特殊之处在于它不改变对象的lru值。
-
refcount引用计数器:refcount记录的是对象被引用的次数,refcount主要用于对象的引用计数和内存回收,是不是想起点什么?对了,就是类似jvm的对象存活判断方法之一引用计数法。当创建新对象时,refcount初始化为1,有程序调用时加一,对象不再被调用时减一,refcount变为0时对象占据的内存则会释放。
-
*ptr数据指针:ptr指针指向具体的数据。
redisServer
RedisServer中对应着redisServer的对象,一个redisServer中可以存在多个数据库实例。
struct redisServer {
// ...
redisDb *db; // redisDb数组,一个redisDb代表着一个redis数据库
int dbnum; // 一个RedisServer中包含的redis数据库个数,可以自定义,默认是16
};
Redis内存数据库,最底层是一个redisDb;
typedef struct redisDb{
dict *dict; //DB数据库
dict *expires; // key过期时间
dict *bl