redis容量估算

工作中常会用到redis做存储型的kv存储,如何合理地估算所占空间呢?

首先要看看redis的存储原理,redis存储时候kv都会被处理成字符串或者说字符数组,redis实现了一种方便进行append,rehash等操作的sds类型。
sds.h可以看到typedef char *sds;这样的定义。光这样和普通的字符串看上去毫无区别,事实上sds有一个header的概念,同样在sds.h里面

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    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[];
};

注意这段注释,sdshdr5不用,但是size小于2^5-1的字符串都会使用SDS_TYPE_5。

在各个header的定义中最后有一个char buf[]。这是柔性数组(flexible array member),起到一个标记的作用,表示在flags字段后面就是一个字符数组,它并不占用内存空间。

看到这里SDS_TYPE5的头只占1个字节,而SDS_TYPE_8则占3个字节

在sds之上还封装了robj,定义如下

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
    int refcount;
    void *ptr;
} robj;

而为了能够快速存储读取,所有的kv保存在dict结构里,而每个dictEntry是这种形式:

typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

key是一个”aaa”的sds指针,v是一个指向包含”bbb”的robj的指针
也就是一个dictEntry占24字节,一个key作为sds占sdsheader+本身内容+结束符(1),而一个v作为一个robj占sds和robj的空间,约12字节。

举例来说,我有一个表存用户登录的token

占用多少空间呢?
假设用户id 19位,token50位,key可以用SDS_TYPE_5,1+19+1=21字节,value要用SDS_TYPE_8了,并包装成robj,即3+12+50+1=66,一个dictEntry24字节

总计下来111个字节,这样单条记录所占空间大致计算出来,估一下数据量就能计算了

猜你喜欢

转载自blog.csdn.net/weixin_41571449/article/details/79781367