Skip to content

Redis set 空间占用分析 #43

Description

@bigwolftime

https://bigwolftime.github.io/Redis-set-Space_occupancy_analysis/

Redis version 2.8.20 OS: 64bit


Redis 中存储字符串的结构为 SDS(简单动态字符串), 其定义包括:

struct sdshdr {
unsigned int len; // 字符串占用总长度
unsigned int free; // 剩余可用长度
char buf[]; // 存储实际的数据, 最后一位追加'\0'为结束标记
};

所以 SDS 占用空间为: 4(len) + 4(free) + n + 1('\0') = 9 + n(单位:byte, n 为字符串长度)

SDS 是对字符串的一个封装, 在其之上会封装一层 RedisObject, 其定义包括:

typedef struct redisObject {
unsigned type:4; // (:4代表占用 4bit)
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS; // REDIS_LRU_BITS = 24
int refcount; // 引用计数, 涉及到空间释放时会用到, 若不为 0 则不能被释放
void *ptr; // 此处指针指向实际的的 SDS 地址
} robj;

RedisObject 占用空间: (4 + 4 + 24) / 8 + 4 + 8 = 16byte
所以总结出一个完整的 RedisObject 对象总空间占用为: 9 + n + 16 = n + 25

其中: Redis 的 tryObjectEncoding 函数会判断指针 ptr 所指向的 SDS 能否转换为整数, 若可以 ptr 直接将其保存为整数, 并释放掉刚才的 SDS.
即: 当 value 可转化为整数时, 总占用为 16byte, 否则为 (n + 25)byte


当执行 set aaa bbb 时, 空间占用分析:
首先 “set” “aaa” “bbb” 会各生成 1 个 RedisObject, 各自占用 (25 + 3)byte.
其中 “set” 用来查找命令 lookupCommand, 完成之后会释放掉RedisObject 结构(仅保留 SDS), “aaa” 这个对象也会用 SDS 存储, 也会释放掉 RedisObject 结构.
所以目前总占用为: 12(SDS(set)) + 12(SDS(aaa)) + 28(RedisObject(bbb)) = 52byte

最后这组键值对最终会存储到dictEntry 结构中, 其定义为:

typedef struct dictEntry {
void *key; // 即上面的

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions