您好,登錄后才能下訂單哦!
最近做的一個系統(tǒng)大量使用redis,我們將大量的用戶信息存放在redis中,內(nèi)存一申請就是幾百G,體量也是相當(dāng)龐大。所以我們也在不斷的想方法優(yōu)化減少redis的內(nèi)存使用,把我們的優(yōu)化實踐也分享出來。
因為是存放用戶維度的數(shù)據(jù),用戶id(uid)往往會作為key,而一個用戶會有多個信息,比如年齡,生日等等,比較容易想到的存儲結(jié)構(gòu)會采用Hash,將一個用戶的多個信息作為hash里的不同field來存放
Redis針對Hash,List,ZSet都實現(xiàn)了ziplist的壓縮存儲,可以通過配置最大元素不超過512,每個元素大小不超過64bytes,來判斷是否要采用 !ziplist壓縮格式 存儲。
注意:雖然這個ziplist是否啟用做成了配置參數(shù),但對這個配置參數(shù)的修改要謹(jǐn)慎,因為ziplist是一個連續(xù)的數(shù)組空間,查找效率不是O(1)的,如果設(shè)置元素超過512太多,可能導(dǎo)致查找效率降低,反而影響性能。那為什么Redis會采用512*64bytes這樣的默認(rèn)配置呢?據(jù)說是這個大小可以被加載進(jìn)CPU的Cache里,所以即使不是O(1),查找效率也是很快的。
在Redis的內(nèi)部,不管是數(shù)字類型,String類型,都會統(tǒng)一用一個叫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就搞定的,還有很多附加的屬性,比如引用計數(shù)(內(nèi)存回收)refcount,lru清理等信息。
但如果使用了上面提到的ziplist,redis對ziplist里元素做了裁剪,讓數(shù)據(jù)更緊湊,所以針對數(shù)字,做了一些特別處理:
* |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,針對大小不同的數(shù)字,分別采用不一樣的內(nèi)存空間來存儲,比如0-127就是2個字節(jié),128-32768就是4個字節(jié)等等。所以算下來,和String相比,大部分情況下更省內(nèi)存。
另外,如果不是采用ziplist的存儲方式,而是直接用redisObject這樣相對龐大的對象存儲呢?
如果能用數(shù)字,還是盡量使用數(shù)字類型,并且是小于10000的數(shù)字最好,因為:
#define OBJ_SHARED_INTEGERS 10000
redis考慮到redisObject這個龐大的對象占用過多內(nèi)存的因素,將10000以下數(shù)字的redisObject做了一個對象池,其他地方都通過指針(4/8bytes)引用這個池里的redisObject,而不是各自存一份。
注: 以上都是針對Redis 3.2之前版本的分析,因為Redis 3.2對內(nèi)存優(yōu)化這部分做了很多改進(jìn),具體的改進(jìn)點還未了解清楚。
最后,對堅持看完的同學(xué)送上一個非常有用的Redis內(nèi)存分析工具: redis-rdb-tools,結(jié)合bgsave的dump文件,分析redis里的數(shù)據(jù),可以看到底層存儲是用的什么數(shù)據(jù)結(jié)構(gòu),占用了多少空間等信息。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。