Redis 相关

数据如何存储

redisObject

  • redisObject 是 Redis 对象系统的统一对象头。
  • Redis 通过 type 表示“对外逻辑类型”,通过 encoding 表示“内部存储结构”,
  • 再通过 ptr 指向真实数据,从而实现同一种逻辑类型的多种底层优化表示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct redisObject {
unsigned type:4; // 对象的逻辑类型,如 string/list/hash/set/zset/stream
unsigned encoding:4; // 对象的底层编码方式,如 raw/embstr/int/listpack/hashtable 等
unsigned refcount : OBJ_REFCOUNT_BITS;
// 引用计数,用于对象共享和内存回收

unsigned iskvobj : 1; // 是否作为 key-value object 的基础对象
// 为 1 时,下面的 metabits 和 lru 字段才有意义

/* metabits and lru are Relevant only when iskvobj is set: */
unsigned metabits :8; // kv 对象的元信息位图
// 可用于标记对象是否绑定了过期时间、额外元数据等

unsigned lru:LRU_BITS; // 对象的 LRU/LFU 信息
// LRU 模式下:记录对象最近访问时间
// LFU 模式下:低 8 位表示访问频率,高 16 位表示访问时间

void *ptr; // 指向对象真实数据的指针
// 例如 string 对象可能指向 SDS
// hash 对象可能指向 listpack 或 dict
// zset 对象可能指向 skiplist/listpack 等
};

接下来看一下 string 的对象 Simple Dynamic string

1
2
3
4
5
6
7
8
9
10
11
12
13
struct __attribute__ ((__packed__)) sdshdr32 { // 告诉编译器:这个结构体不要自动插入 padding 对齐字节,尽量紧凑排列。
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[];
};