Redis數(shù)據(jù)存儲優(yōu)化機制詳解
zipmap優(yōu)化hash
將一個對象存儲在hash類型中會占用更少的內(nèi)存,并且可以更方便的存取整個對象。省內(nèi)存的原因是新建一個hash對象時開始是用zipmap來存儲的。這個zipmap其實并不是hash table,但是zipmap相比正常的hash實現(xiàn)可以節(jié)省不少hash本身需要的一些元數(shù)據(jù)存儲開銷。盡管zipmap的添加,刪除,查找都是O(n),但是由于一般對象的field數(shù)量都不太多。所以使用zipmap也是很快的,也就是說添加刪除平均還是O(1)。
如果field或者value的大小超出一定限制后,redis會在內(nèi)部自動將zipmap替換成正常的hash實現(xiàn)。這個限制可以在配置文件中指定(默認配置在redis根目錄下的redis.conf中):
- hash-max-zipmap-entries 512 #配置字段最多512個
- hash-max-zipmap-value 64 #配置value***為64字節(jié)
ziplist優(yōu)化list
如果redisObject的type成員值是REDIS_LIST類型的,則當該list的元素個數(shù)小于配置值list-max-ziplist-entries,且元素值字符串的長度小于配置值list-max-ziplist-value,
則可以編碼成 REDIS_ENCODING_ZIPLIST 類型存儲,否則采用 Dict 來存儲(Dict實際是Hash Table的一種實現(xiàn)),list采用ziplist數(shù)據(jù)結(jié)構(gòu)存儲數(shù)據(jù),這樣做一方面為了節(jié)省內(nèi)存,另一方面這種結(jié)構(gòu)式順序存儲的結(jié)構(gòu),能夠更好利用cpu local和預(yù)取策略。
配置如下所示:
- list-max-ziplist-entries 512 #配置元素個數(shù)最多512個
- list-max-ziplist-value 64 #配置value***為64字節(jié)
intset優(yōu)化set
當set集合中的元素為整數(shù)且元素個數(shù)小于配置set-max-intset-entries值時,使用intset數(shù)據(jù)結(jié)構(gòu)存儲,否則轉(zhuǎn)化為Dict結(jié)構(gòu),Dict實際是Hash Table的一種實現(xiàn),key為元素值,value為NULL,這樣即可在O(1)時間內(nèi)判斷集合中是否包含某個元素。
intset中有三種類型數(shù)組:int16_t類型、int32_t 類型、 int64_t 類型。至于怎么選擇是那種類型的數(shù)組,是根據(jù)其保存的值的取值范圍來決定的,初始化時是 int16_t,根據(jù) set 中的***值在[INT16_MIN, INT16_MAX] , [INT32_MIN, INT32_MAX], [INT64_MIN, INT64_MAX]的那個取值范圍來動態(tài)確定整個數(shù)組的類型。例如set一開始是 int16_t 類型,當一個取值范圍在 [INT32_MIN, INT32_MAX]的值加入到 set 時,則將保存 set 的數(shù)組升級成 int32_t 的數(shù)組。
intset元素限制的配置如下所示:
- set-max-intset-entries 512 #配置元素個數(shù)最多512個
ziplist優(yōu)化sorted set
根hash和list一樣sorted set也有節(jié)約內(nèi)存的方式,當sorted set的元素個數(shù)及元素大小小于一定限制時,它是用ziplist來存儲。
這個限制的配置如下:
- zset-max-ziplist-entries 128 #配置元素個數(shù)最多512個
- zset-max-ziplist-value 64 #配置value***為64字節(jié)
小結(jié)
Redis提供了很多關(guān)于優(yōu)化內(nèi)存的方法,上面這些配置的值都是默認配置,實際要根據(jù)我們具體的需求場景來調(diào)節(jié),并要做大量的測試,以達到***的效果。同時必須對Redis這些數(shù)據(jù)結(jié)構(gòu)有很好的理解。