redis 內存優化

最近做的一個系統大量使用redis,我們將大量的用戶信息存放在redis中,內存一申請就是幾百G,體量也是相當龐大。所以我們也在不斷的想方法優化減少redis的內存使用,把我們的優化實踐也分享出來。

採用Hash代替<K,V>鍵值對存儲

因爲是存放用戶維度的數據,用戶id(uid)往往會作爲key,而一個用戶會有多個信息,比如年齡,生日等等,比較容易想到的存儲結構會採用Hash,將一個用戶的多個信息作爲hash裏的不同field來存放

善用Hash,List,ZSet的ziplist壓縮特性

Redis針對Hash,List,ZSet都實現了ziplist的壓縮存儲,可以通過配置最大元素不超過512,每個元素大小不超過64bytes,來判斷是否要採用 !ziplist壓縮格式 存儲。

注意:雖然這個ziplist是否啓用做成了配置參數,但對這個配置參數的修改要謹慎,因爲ziplist是一個連續的數組空間,查找效率不是O(1)的,如果設置元素超過512太多,可能導致查找效率降低,反而影響性能。那爲什麼Redis會採用512*64bytes這樣的默認配置呢?據說是這個大小可以被加載進CPU的Cache裏,所以即使不是O(1),查找效率也是很快的。

優先使用數字類型,比String類型省空間

在Redis的內部,不管是數字類型,String類型,都會統一用一個叫redisObject的對象做一層封裝:

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

可見,一個簡簡單單的”hello world”在redis裏都不是直接11個bytes就搞定的,還有很多附加的屬性,比如引用計數(內存回收)refcount,lru清理等信息。

但如果使用了上面提到的ziplist,redis對ziplist裏元素做了裁剪,讓數據更緊湊,所以針對數字,做了一些特別處理:

* |11000000| - 1 byte* Integer encoded as int16_t (2 bytes).
* |11010000| - 1 byte* Integer encoded as int32_t (4 bytes).
* |11100000| - 1 byte* Integer encoded as int64_t (8 bytes).
* |11110000| - 1 byte* Integer encoded as 24 bit signed (3 bytes).
* |11111110| - 1 byte* Integer encoded as 8 bit signed (1 byte).
* |1111xxxx| - (with xxxx between 0000 and 1101) immediate 4 bit integer.
* Unsigned integer from 0 to 12. The encoded value is actually from* 1 to 13 because 0000 and 1111 can not be used, so 1 should be
* subtracted from the encoded 4 bit value to obtain the right value.

先用1byte來表示不同的encode,針對大小不同的數字,分別採用不一樣的內存空間來存儲,比如0-127就是2個字節,128-32768就是4個字節等等。所以算下來,和String相比,大部分情況下更省內存。

另外,如果不是採用ziplist的存儲方式,而是直接用redisObject這樣相對龐大的對象存儲呢?

如果能用數字,還是儘量使用數字類型,並且是小於10000的數字最好,因爲:

#define OBJ_SHARED_INTEGERS 10000

redis考慮到redisObject這個龐大的對象佔用過多內存的因素,將10000以下數字的redisObject做了一個對象池,其他地方都通過指針(4/8bytes)引用這個池裏的redisObject,而不是各自存一份。

注: 以上都是針對Redis 3.2之前版本的分析,因爲Redis 3.2對內存優化這部分做了很多改進,具體的改進點還未了解清楚。

最後,對堅持看完的同學送上一個非常有用的Redis內存分析工具: redis-rdb-tools,結合bgsave的dump文件,分析redis裏的數據,可以看到底層存儲是用的什麼數據結構,佔用了多少空間等信息。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章