Redis存储优化--小对象压缩
生活随笔
收集整理的這篇文章主要介紹了
Redis存储优化--小对象压缩
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
小對象壓縮
- Redis是一種內(nèi)存數(shù)據(jù)庫,內(nèi)存是計(jì)算機(jī)中一種比較寶貴的資源,如果我們不注意節(jié)約,Redis很可能出現(xiàn)內(nèi)存不足,最終導(dǎo)致崩潰。Redis為了優(yōu)化數(shù)據(jù)結(jié)構(gòu)的內(nèi)存占用,增加了非常多的優(yōu)化點(diǎn),這些優(yōu)化也是犧牲代碼的可讀性為代價(jià),但是對于解決的內(nèi)存問題來說是非常值得的,尤其是對于Redis這種內(nèi)存數(shù)據(jù)庫
32bit VS 64bit
- Redis如果使用32bit版本,內(nèi)部存儲所有數(shù)據(jù)結(jié)構(gòu)使用的指針空間占用會少一半,如果Redis使用內(nèi)存不會超過2^32 = 4GB,可以考慮32bit進(jìn)行編譯,能節(jié)約大量內(nèi)存。4GB容量對小站點(diǎn)來說戳戳由于。不足可以增加節(jié)點(diǎn)
- 指針是尋址,存儲的是地址信息,32bit系統(tǒng)能表示的總大小是2^32 位,所以指針能表示的尋址最大值也就是 2 ^32,同理64bit 系統(tǒng)占用2 ^ 64
小對象壓縮
- 如果Redis內(nèi)部管理的集合數(shù)據(jù)結(jié)構(gòu)很小,他會使用緊湊型存儲形式壓縮存儲,只有當(dāng)集合數(shù)據(jù)達(dá)到一定量級的時(shí)候,Redis才會將數(shù)據(jù)存儲稱為正常我們熟知的狀態(tài)。
- 例如HashMap本來是二維結(jié)構(gòu),如果內(nèi)部元素少,使用數(shù)組+鏈表的形式反而浪費(fèi)空間,因?yàn)橹羔樥加每臻g比數(shù)據(jù)還要多,還不如使用一維數(shù)組進(jìn)行存儲,查找時(shí)候元素少,遍歷也快,只不過代碼略復(fù)雜而已。以下案例用一維數(shù)組存儲HashMap的CUD
- 同樣Redis的ziplist是一個緊湊型的字節(jié)數(shù)組結(jié)構(gòu),如下圖中所示,每個元素都是緊密相連,中間沒有指針用來尋址操作,通過三個全局指針來完成邏輯處理,zlbytes, zltail和zlend。如下:
- 如果如上結(jié)果存儲的是hash結(jié)構(gòu),那么key和value作為兩個entry,被相鄰的兩個entry存儲,通過如下方式驗(yàn)證,輸出類型是ziplist:
- 如果存儲的類型是zset,那么value和score會作為兩個entry被相鄰存儲
- 整數(shù)的存儲Redis有一個叫intset的整數(shù)數(shù)組結(jié)構(gòu),用于存放元素都是整數(shù)且元素個數(shù)較少的set集合。
- 如果整數(shù)可以用uint16標(biāo)識,那么intset的元素就是16位的數(shù)組,如果新加入的整數(shù)超過uint16,那么久用uint32,還不夠則用uint64,Redis支持set集合動態(tài)從unit16升級到unit32,在到unit64
- 如下代碼,我們在set集合中存儲的數(shù)字,他的類型就是intset
- 如果set存儲的字符串,那么sadd會升級為hashtable結(jié)構(gòu),
總結(jié)
hash - max-z 工pl 工 st entries 512 結(jié)構(gòu)存儲 # hash 的元素個數(shù)超過 512 就必須用標(biāo)準(zhǔn) hash- max-ziplist-value 64 超過 64 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 # hash 的任意元素的 key/value 的長度超過64 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 list-max-ziplist-entries 512 結(jié)構(gòu)存儲 # list 的元素個數(shù)超過 512 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 list-max-z 工plist - value 64 用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 # list 的任意元素的長度超過 64 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 zset-max-ziplist-entries 128 結(jié)構(gòu)存儲 # zset 的元素個數(shù)超過 128 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 zset-max- ziplist-value 64 用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 # zset 的任意元素的長度超過 64 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲 set-max-intset-entries 512 標(biāo)準(zhǔn)結(jié)構(gòu)存儲 # set 的整數(shù)元素個數(shù)超過 512 就必須用標(biāo)準(zhǔn)結(jié)構(gòu)存儲- 如下測試代碼:
- 當(dāng)Hash結(jié)構(gòu)元素超過512 ,存儲結(jié)構(gòu)發(fā)生變化其他的也都同理,我們通過如上總結(jié)數(shù)據(jù)看出,當(dāng)hash結(jié)構(gòu)的任意entry的value超過64 ,存儲結(jié)構(gòu)就升級成標(biāo)準(zhǔn)結(jié)構(gòu)。
內(nèi)存回收機(jī)制
- Redis并不總是將空閑內(nèi)存理解歸還操作系統(tǒng)
- 例如Redis內(nèi)存10GB,當(dāng)刪除1GBkey后,觀察內(nèi)存,并不會太大變化,因?yàn)椴僮飨到y(tǒng)是以頁為單位回收內(nèi)存,這個頁內(nèi)只要還有一個key,就不會被回收。Redis雖然刪除了1GBkey但是這些key是分散到各個page中,每個page都還有其他key,這就導(dǎo)致內(nèi)不會被立刻回收。
- 我們執(zhí)行flushdb,觀察內(nèi)存,他就會重新使用那些尚未回收的空閑內(nèi)存。就比如一個page中只有一個key,次數(shù)set另一個key,他會存儲在這個page的空閑內(nèi)存中。
內(nèi)存分配算法
- 內(nèi)存分配是比較復(fù)雜的,需要是的劃分內(nèi)存頁,考慮內(nèi)存碎片,需要平衡性能與效率
- Redis為保證自身結(jié)構(gòu)簡單,目前沒有自己做內(nèi)存分配策略,由第三方庫完成此部分內(nèi)容,
- Redis可以用jemalloc,facebook的庫來管理內(nèi)存
- Redis也可以切換到tcmalloc,google的庫來管理
- jemalloc性能優(yōu)于tcmalloc,Redis默認(rèn)使用jemalloc
- 通過info memory指令可以看到Redis的 mem_allocator:jemalloc-4.0.3使用的jemalloc-4.0.3
上一篇:Redis–事務(wù)理解
下一篇:Redis高可用基石–主從同步
總結(jié)
以上是生活随笔為你收集整理的Redis存储优化--小对象压缩的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外阴瘙痒用高锰酸钾管用吗
- 下一篇: 消息称三星电子已终止与京东方合作,不再采