初学Redis的时候,一脸懵逼,完全不知道Redis是如何表示一个数据库的。慢慢发现一个数据库就是一个字典(dict)数据结构。
下图中,数据库中存储了一个Key = hello, value = 57678900(int)的键值对,图中的其他字段后续会慢慢说明
由图中可知,数据库中的每个键、值,以及 Redis 本身处理的参数,都表示为redisObject数据类型。
typedef struct redisObject {
// 类型
unsigned type:4;
// 对齐位
unsigned notused:2;
// 编码方式
unsigned encoding:4;
// LRU 时间(相对于 server.lruclock)
unsigned lru:22;
// 引用计数
int refcount;
// 指向对象的值
void *ptr;
} robj;
type记录了对象的类型。主要有:
#define REDIS_STRING 0 // 字符串
#define REDIS_LIST 1 // 列表
#define REDIS_SET 2 // 集合
#define REDIS_ZSET 3 // 有序集
#define REDIS_HASH 4 // 哈希表
encoding表示对象所保存值得编码方式,即值记录值所采用的数据结构
#define REDIS_ENCODING_RAW 0 // 编码为字符串
#define REDIS_ENCODING_INT 1 // 编码为整数
#define REDIS_ENCODING_HT 2 // 编码为哈希表
#define REDIS_ENCODING_ZIPMAP 3 // 编码为 zipmap
#define REDIS_ENCODING_LINKEDLIST 4 // 编码为双端链表
#define REDIS_ENCODING_ZIPLIST 5 // 编码为压缩列表
#define REDIS_ENCODING_INTSET 6 // 编码为整数集合
#define REDIS_ENCODING_SKIPLIST 7 // 编码为跳跃表
而ptr指针指向实际保存值的数据结构,这个数据结构由 type 属性和 encoding 属性决定。
举例说明:如果type = REDIS_LIST , encoding = REDIS_ENCODING_LINKEDLIST. 那么这个对象就是一个 Redis 列表,它的值保存在一个双端链表内,而 ptr 指针就指向这个双端链表;
lru记录与server.lruclock的时间差值。后续会说明。
refcount记录该对象被应用的次数。
值得注意的是在Redist中还存在对象共享的概念,和Java中的常量池有点类似。即通过预分配一些常见的值对象,并在多个数据结构之间共享这些对象(共享对象只能被带指针的数据结构使用)。主要有两类:
1.命令返回值:OK、ERROR等
2.0~10000的整数