Redis記憶體節省策略

來源:互聯網
上載者:User

     Redis作為一款緩衝軟體,在Redis的源碼中,處處體現著節省記憶體的思想,下面先從3個方面對Redis的記憶體節省策略做一個分享。(以下代碼為Redis 3.0.5版本)

      1.redisObject 是Redis中最常見的一個資料結構,Redis儲存的所有的鍵和值都是一個redisObject, 因此必須盡肯能節省redisObject的大小。由於Redis 資料類型只有我們所常見的5種,而Redis的資料編碼類別型總共8種,所以Redis中分別採用4Bit來表示,兩者相加正好1個位元組。

                        

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;
          2.Redis對於經常使用變數,將其設為全域變數,並採用引用計數的方法。本策略主要目的是為了避免重複的建立,提高效能。只有當足夠數量的資料值在0-9999時才會發揮節省記憶體的作用。如代碼所示,在結構體中有一個變數integers, 裡面儲存著資料0-9999的對象指標。

struct sharedObjectsStruct {    robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space,    *colon, *nullbulk, *nullmultibulk, *queued,    *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,    *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr,    *masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,    *busykeyerr, *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk,    *unsubscribebulk, *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop,    *lpush, *emptyscan, *minstring, *maxstring,    *select[REDIS_SHARED_SELECT_CMDS],    *integers[REDIS_SHARED_INTEGERS],    *mbulkhdr[REDIS_SHARED_BULKHDR_LEN], /* "*<value>\r\n" */    *bulkhdr[REDIS_SHARED_BULKHDR_LEN];  /* "$<value>\r\n" */};

      3.Redis的8種編碼類別型,REDIS_ENCODING_INT, REDIS_ENCODING_EMBSTR, REDIS_ENCODING_RAW是基礎,對於其他幾種編碼類別型,除REDIS_ENCODING_INTSET外,其所對應Object Storage Service的資訊對象均是以前三種編碼類別型為基礎,產生一個個具體的對象。如Redis鏈表中,每個節點儲存的對象,其編碼類別型可以為REDIS_ENCODING_INT, REDIS_ENCODING_EMBSTR, REDIS_ENCODING_RAW 中的任意一種。

/* Try to encode a string object in order to save space */robj *tryObjectEncoding(robj *o) {    long value;    sds s = o->ptr;    size_t len;    /* Make sure this is a string object, the only type we encode     * in this function. Other types use encoded memory efficient     * representations but are handled by the commands implementing     * the type. */    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);    /* We try some specialized encoding only for objects that are     * RAW or EMBSTR encoded, in other words objects that are still     * in represented by an actually array of chars. */    if (!sdsEncodedObject(o)) return o;    /* It's not safe to encode shared objects: shared objects can be shared     * everywhere in the "object space" of Redis and may end in places where     * they are not handled. We handle them only as values in the keyspace. */     if (o->refcount > 1) return o;    /* Check if we can represent this string as a long integer.     * Note that we are sure that a string larger than 21 chars is not     * representable as a 32 nor 64 bit integer. */    len = sdslen(s);    if (len <= 21 && string2l(s,len,&value)) {        /* This object is encodable as a long. Try to use a shared object.         * Note that we avoid using shared integers when maxmemory is used         * because every object needs to have a private LRU field for the LRU         * algorithm to work well. */        if ((server.maxmemory == 0 ||             (server.maxmemory_policy != REDIS_MAXMEMORY_VOLATILE_LRU &&              server.maxmemory_policy != REDIS_MAXMEMORY_ALLKEYS_LRU)) &&            value >= 0 &&            value < REDIS_SHARED_INTEGERS)        {            decrRefCount(o);            incrRefCount(shared.integers[value]);            return shared.integers[value];        } else {            if (o->encoding == REDIS_ENCODING_RAW) sdsfree(o->ptr);            o->encoding = REDIS_ENCODING_INT;            o->ptr = (void*) value;            return o;        }    }    /* If the string is small and is still RAW encoded,     * try the EMBSTR encoding which is more efficient.     * In this representation the object and the SDS string are allocated     * in the same chunk of memory to save space and cache misses. */    if (len <= REDIS_ENCODING_EMBSTR_SIZE_LIMIT) {        robj *emb;        if (o->encoding == REDIS_ENCODING_EMBSTR) return o;        emb = createEmbeddedStringObject(s,sdslen(s));        decrRefCount(o);        return emb;    }    /* We can't encode the object...     *     * Do the last try, and at least optimize the SDS string inside     * the string object to require little space, in case there     * is more than 10% of free space at the end of the SDS string.     *     * We do that only for relatively large strings as this branch     * is only entered if the length of the string is greater than     * REDIS_ENCODING_EMBSTR_SIZE_LIMIT. */    if (o->encoding == REDIS_ENCODING_RAW &&        sdsavail(s) > len/10)    {        o->ptr = sdsRemoveFreeSpace(o->ptr);    }    /* Return the original object. */    return o;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.