bigwolftime / gitmentCommentsPlugin

0 stars 0 forks source link

Redis set 空间占用分析 – LOFFER – 一个可以fork的博客 #6

Open bigwolftime opened 4 years ago

bigwolftime commented 4 years ago

https://index1024.gitee.io/blog/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; // 即上面的

bigwolftime commented 4 years ago

.

bigwolftime commented 4 years ago

qq

bigwolftime commented 3 years ago

..