鑑於redis是純記憶體資料庫,為了盡可能的節省記憶體開銷避免因為記憶體不足而崩潰,redis對一部分資料結構進行了優化。
編譯
如果使用32位進行編譯,內部所有資料結構所使用的指標空間占用會少一半,如果使用記憶體不超過4g,可以考慮使用32位進行編譯,如果不足還可以通過增加例項的方式來解決。
壓縮
這裡有個ziplist技術,可以說道說道。當集合資料結構很小的話,那麼它會使用緊湊儲存形式壓縮儲存。
ziplist是類似於位元組陣列結構的壓縮列表,列表中每個元素僅僅相鄰:
該陣列[0]佔4位元組,標記儲存整個ziplist占用的總位元組數。
該陣列[1]佔4位元組,標記最後乙個entry的偏移量,方便直接定位尾部元素。
該陣列[2]佔2位元組,ziplist中entry的數量。
該陣列[length-1]佔1位元組,內容就是255用來標記結束。
陣列其他元素都是entry。
其實,ziplist、 intset為了解除集合資料結構很少的時候而採取的方法。
intset跟ziplist類似,是乙個緊湊的整數陣列結構,它用於存放元素都是整數的並且元素個數較少的 set 集合。如果整數可以用 uint16 表示,那麼 intset 的元素就是 16 位的陣列,如果新加入的整數超過了 uint16 的表示範圍,那麼就使用 uint32 表示,如果新加入的元素超過了 uint32 的表示範圍,那麼就使用 uint64 表示,redis 支援 set 集合動態從 uint16 公升級到 uint32,再公升級到 uint64。
當集合物件的元素不斷增加或者某個value值過大,這種小物件儲存也會被公升級為標準結構。redis規定在小物件儲存結構的限制條件如下:
hash-max-zipmap-entries 512 # hash 的元素個數超過 512 就必須用標準結構儲存
hash-max-zipmap-value 64 # hash 的任意元素的 key/value 的長度超過 64 就必須用標準結構儲存
list-max-ziplist-entries 512 # list 的元素個數超過 512 就必須用標準結構儲存
list-max-ziplist-value 64 # list 的任意元素的長度超過 64 就必須用標準結構儲存
zset-max-ziplist-entries 128 # zset 的元素個數超過 128 就必須用標準結構儲存
zset-max-ziplist-value 64 # zset 的任意元素的長度超過 64 就必須用標準結構儲存
set-max-intset-entries 512 # set 的整數元素個數超過 512 就必須用標準結構儲存
說白了,就是redis可以控制小物件壓縮與標準結構儲存之間轉換。
記憶體**
redis並不總是可以將空閒記憶體立即歸還給作業系統。
原因是作業系統**記憶體是以頁為單位,如果這個頁上只要有乙個key還在使用,那麼它就不能被**。key分散到了很多頁面中,每個頁面都還有其它key存在,這就導致了記憶體不會立即被**。
redis為了保持自身結構的簡單性,在記憶體分配這裡直接讓第三方記憶體分配庫去實現。目前 redis 可以使用 jemalloc(facebook) 庫來管理記憶體,也可以切換到tcmalloc(google)。因為 jemalloc 相比 tcmalloc的效能要稍好一些,所以redis預設使用了jemalloc。
Redis 小物件壓縮
redis 是乙個非常耗費記憶體的資料庫,它所有的資料都放在記憶體裡。如果我們不注意節約使用記憶體,redis 就會因為我們的無節制使用出現記憶體不足而崩潰。1 ziplist 是乙個緊湊的位元組陣列結構,每個元素直接都是緊挨著,資料結構如下圖 1 object encoding key 查詢key...
Redis儲存優化 小物件壓縮
小物件壓縮 32bit vs 64bit 小物件壓縮 public class arraymap keys.add k values.add v return null public v get k k return null public v delete k k return null 新doc...
Redis小物件的壓縮儲存
redis hash是value內部為乙個hashmap,如果該map的成員數比較少,則會採用類似一維線性的緊湊格式來儲存該map,即省去了大量指標的記憶體開銷,這個引數控制對應在redis.conf配置檔案中下面2項 以上2個條件任意乙個條件超過設定值都會轉換成真正的hashmap,也就不會再節省...