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