redis:stringタイプの原理と実現

2377 ワード

redisはkey-valueデータベースとしてstringが基本データ型である.
redisのすべてのkeysは文字列タイプであり、文字列タイプもvaluesの基本データタイプである.他のより複雑なデータ型であるlists,sets,sorted sets,hashesも文字列を使用して実現されています.
redis stringデータ型の実現はsdsに含まれる.c(sds、すなわちSimple Dynamic Strings、単純な動的文字列)にある.C言語構造体sdshdrはsds.hで宣言され、redis stringタイプを表します.
struct sdshdr {
    long len;
    long free;
    char buf[];
};

文字配列bufは実際の文字列を格納する.
len変数は文字列の長さを保存し、文字列の長さを取得する時間の複雑さはO(1)である.
free変数はbufで利用可能な空間を格納する.
lenとfreeはbuf文字配列のメタ情報を保存した.
  • redis文字列
  • を作成する
    sds.hではsdsという新しいデータ型が定義されていますが、実は文字列ポインタです.
    typedef char *sds;

    sds.cで定義したsdsnewlen関数は、新しい文字列を作成するために使用されます.
    sds sdsnewlen(const void *init, size_t initlen) {
        struct sdshdr *sh;
    
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    #ifdef SDS_ABORT_ON_OOM
        if (sh == NULL) sdsOomAbort();
    #else
        if (sh == NULL) return NULL;
    #endif
        sh->len = initlen;
        sh->free = 0;
        if (initlen) {
            if (init) memcpy(sh->buf, init, initlen);
            else memset(sh->buf,0,initlen);
        }
        sh->buf[initlen] = '\0';
        return (char*)sh->buf;
    }

    redis stringはsdshdrタイプの変数ですが、この関数は文字列ポインタを返します.
    これは小さなテクニックです.ここで説明します.sdsnewlenを使用して文字列「redis」を作成するとします.
    sdsnewlen("redis", 5);

    この関数はstruct sdshdrタイプ変数を作成し、len、free、bufにメモリ領域を割り当てます.
    struct sdshdr *sh;
    sh = zmalloc(sizeof(struct sdshdr)+initlen+1);

    sdsnewlenの作成に成功した後、
    の構造を持つredis stringが得られた.
    -----------
    |5|0|redis|
    -----------
    ^   ^
    sh  sh->buf
    
    

    sdsnewlenはsh->bufを呼び出し元に返します.
    では、shが指すredis stringを解放する必要がある場合は、どうすればいいのでしょうか.
    shを指すポインタが必要ですが、sh->bufを指すポインタが必要です.
    sh->bufからshを指すポインタをもらえますか?
    いいですよ.ポインタによる演算.以上のASCIIプロットから,sh->bufから2つのlong型サイズを減算するとshを指すポインタが得られることが分かる.2つのlong型の大きさはstruct sdshdrの大きさである.sdslen関数がどのように機能しているかを見てみましょう.
    size_t sdslen(const sds s) {
        struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
        return sh->len;
    }
    このテクニックを理解すると、sdsを理解しやすくなります.cの他の関数.
    redis stringの実装はインタフェースの後ろに隠されており、このインタフェースは文字列ポインタのみを受け入れる.redis stringのユーザは,その具体的な実装に関心を持つ必要はなく,文字列ポインタと見なせばよい.
    原文:http://redis.io/topics/internals-sds