redis容量推定

4360 ワード

仕事で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[];
};

この注記はsdshdr 5では使用しませんが、sizeが2^5-1未満の文字列ではSDS_が使用されます.TYPE_5.
各ヘッダの定義に最後にchar buf[]があります.これはフレキシブル配列(flexible array member)であり、flagsフィールドの後ろに文字配列があり、メモリ領域を占有しないことを示すタグとして機能します.
ここを見てSDS_TYPE 5のヘッダは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バイトを占め、1つのkeyがsdsがsdshader+自体のコンテンツ+エンドマーク(1)を占め、1つのvがrobjがsdsとrobjの空間を占め、約12バイトである.
たとえば、ユーザーログインのtokenを格納するテーブルがあります.
どのくらいのスペースを占有しますか?ユーザID 19ビット、token 50ビットを仮定すると、keyはSDS_TYPE_5,1+19+1=21バイト、valueはSDS_TYPE_8になり、robj、すなわち3+12+50+1=66に包装され、dictEntry 24バイト
合計111バイトということで、1つのレコードが占めるスペースをおおよそ算出し、データ量を見積もって計算することができます