Redis基礎知識----SDS(単純動的文字列)
以下のまとめは、redisソース4.0.9バージョンに基づいています。 1.redisの最下位記憶データ構造単純動的文字列(SDS)、チェーンテーブル、辞書、ジャンプテーブル、ツリー全体集合、圧縮リストなど2、redisのデータ構造オブジェクト文字列、リスト、ハッシュ、集合、秩序集合など
len
およびalloc
の属性がなく、flags
の高さ5ビットを巧みに使用して文字列の長さを識別します. sdshdr5 ----> <32
sdshdr8 ----> <256
sdshdr16 ----> < 2^16
sdshdr32 ----> < 2^32
sdshdr64 ----> < 2^64
基本的なデータ構造は次のとおりです.
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[];
};
len
は文字列の真の長さを表します.alloc
ヘッダーとterminator以外の割当長を除外flags
型は、構造体の実際のタイプを識別するbuf[]
実際のデータsdshdr5
データ構造struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
文字列の拡張
/*
* SDS
*
*
* 1. s: SDS
* 2. addlen:
*
*
* sds, sds
*/
sds sdsMakeRoomFor(sds s, size_t addlen) {
void *sh, *newsh;
// SDS
size_t avail = sdsavail(s);
size_t len, newlen;
char type, oldtype = s[-1] & SDS_TYPE_MASK;
int hdrlen;
/* Return ASAP if there is enough space left. */
//
if (avail >= addlen) return s;
len = sdslen(s);
// sds( , )
// , void *sh
sh = (char*)s-sdsHdrSize(oldtype);
newlen = (len+addlen);
// 2
// SDS_MAX_PREALLOC
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += SDS_MAX_PREALLOC;
// ,
type = sdsReqType(newlen);
// SDS_TYPE_5 ( ),
// , SDS_TYPE_8
if (type == SDS_TYPE_5) type = SDS_TYPE_8;
hdrlen = sdsHdrSize(type);
if (oldtype==type) {
//
newsh = s_realloc(sh, hdrlen+newlen+1);
if (newsh == NULL) return NULL;
s = (char*)newsh+hdrlen;
} else {
/* Since the header size changes, need to move the string forward,
* and can't use realloc */
// SDS
newsh = s_malloc(hdrlen+newlen+1);
if (newsh == NULL) return NULL;
memcpy((char*)newsh+hdrlen, s, len+1);
//
s_free(sh);
s = (char*)newsh+hdrlen;
//
s[-1] = type;
sdssetlen(s, len);
}
//
sdssetalloc(s, newlen);
return s;
}
重要なポイント:1.SDSの記録長、O(1)は全長2を取得する.文字列の変更時にメモリが割り当てられる回数を減らします.メモリの事前割り当て、一定の長さの文字列を割り当て、拡張時に拡張に必要なlenがSDS_より小さい場合MAX_PREALLOCは、lenの2倍に拡大し、そうでなければSDS_を拡大するMAX_PREALLOC(1M)(
#define SDS_MAX_PREALLOC (1024*1024)
).lenとallocで不活性な解放を実現し、文字列削除後、長さは変わらず、次回の使用に便利です.3.バイナリセキュリティ.空の文字で文字列の終わりを判断するのではなく、lenという属性で判断します.4.キャッシュのオーバーフローを防止します.文字列をマージする前に、現在の文字列の長さ、不足、拡張がチェックされます.ルールは2.