1、常用記憶體優化手段與引數
通過我們上面的一些實現上的分析可以看出redis實際上的記憶體管理成本非常高,即占用了過多的記憶體,作者對這點也非常清楚,所以提供了一系列的引數和手段來控制和節省記憶體,我們分別來討論下。
首先最重要的一點是不要開啟redis的vm選項,即虛擬記憶體功能,這個本來是作為redis儲存超出物理記憶體資料的一種資料在記憶體與磁碟換入換出的乙個持久化策略,但是其記憶體管理成本也非常的高,並且我們後續會分析此種持久化策略並不成熟,所以要關閉vm功能,請檢查你的redis.conf檔案中 vm-enabled 為 no。
其次最好設定下redis.conf中的maxmemory選項,該選項是告訴redis當使用了多少物理記憶體後就開始拒絕後續的寫入請求,該引數能很好的保護好你的redis不會因為使用了過多的物理記憶體而導致swap,最終嚴重影響效能甚至崩潰。
另外redis為不同資料型別分別提供了一組引數來控制記憶體使用,我們在前面詳細分析過redis hash是value內部為乙個hashmap,如果該map的成員數比較少,則會採用類似一維線性的緊湊格式來儲存該map, 即省去了大量指標的記憶體開銷,這個引數控制對應在redis.conf配置檔案中下面2項:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
hash-max-zipmap-entries
含義是當value這個map內部不超過多少個成員時會採用線性緊湊格式儲存,預設是64,即value內部有64個以下的成員就是使用線性緊湊儲存,超過該值自動轉成真正的hashmap。
hash-max-zipmap-value 含義是當 value這個map內部的每個成員值長度不超過多少位元組就會採用線性緊湊儲存來節省空間。
以上2個條件任意乙個條件超過設定值都會轉換成真正的hashmap,也就不會再節省記憶體了,那麼這個值是不是設定的越大越好呢,答案當然是否定的,hashmap的優勢就是查詢和操作的時間複雜度都是o(1)的,而放棄hash採用一維儲存則是o(n)的時間複雜度,如果
成員數量很少,則影響不大,否則會嚴重影響效能,所以要權衡好這個值的設定,總體上還是最根本的時間成本和空間成本上的權衡。
同樣類似的引數還有:
list-max-ziplist-entries 512說明:list資料型別多少節點以下會採用去指標的緊湊儲存格式。
list-max-ziplist-value 64 說明:list資料型別節點值大小小於多少位元組會採用緊湊儲存格式。
set-max-intset-entries 512 說明:set資料型別內部資料如果全部是數值型,且包含多少節點以下會採用緊湊格式儲存。
最後想說的是redis內部實現沒有對記憶體分配方面做過多的優化,在一定程度上會存在記憶體碎片,不過大多數情況下這個不會成為redis的效能瓶頸,不過如果在redis內部儲存的大部分資料是數值型的話,redis內部採用了乙個shared integer的方式來省去分配記憶體的開銷,即在系統啟動時先分配乙個從1~n 那麼多個數值物件放在乙個池子中,如果儲存的資料恰好是這個數值範圍內的資料,則直接從池子裡取出該物件,並且通過引用計數的方式來共享,這樣在系統儲存了大量數值下,也能一定程度上節省記憶體並且提高效能,這個引數值n的設定需要修改源**中的一行巨集定義redis_shared_integers,該值預設是10000,可以根據自己的需要進行修改,修改後重新編譯就可以了。
2、redis持久化磁碟io方式及其帶來的問題
有redis線上運維經驗的人會發現redis在物理記憶體使用比較多,但還沒有超過實際物理記憶體總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持久化的fork系統呼叫造成記憶體占用加倍而導致的,這種觀點是不準確的,因為fork 呼叫的copy-on-write機制是基於作業系統頁這個單位的,也就是只有有寫入的髒頁會被複製,但是一般你的系統不會在短時間內所有的頁都發生了寫入而導致複製,那麼是什麼原因導致redis崩潰的呢?
答案是redis的持久化使用了buffer io造成的,所謂buffer io是指redis對持久化檔案的寫入和讀取操作都會使用物理記憶體的page cache,而大多數資料庫系統會使用direct io來繞過這層page cache並自行維護乙個資料的cache,而當redis的持久化檔案過大(尤其是快照檔案),並對其進行讀寫時,磁碟檔案中的資料都會被載入到物理記憶體中作為作業系統對該檔案的一層cache,而這層cache的資料與redis記憶體中管理的資料實際是重複儲存的,雖然核心在物理記憶體緊張時會做page cache的剔除工作,但核心很可能認為某塊page cache更重要,而讓你的程序開始swap ,這時你的系統就會開始出現不穩定或者崩潰了。我們的經驗是當你的redis物理記憶體使用超過記憶體總容量的3/5時就會開始比較危險了。
3、總結:
1.根據業務需要選擇合適的資料型別,並為不同的應用場景設定相應的緊湊儲存引數。
2.當業務場景不需要資料持久化時,關閉所有的持久化方式可以獲得最佳的效能以及最大的記憶體使用量。
3.如果需要使用持久化,根據是否可以容忍重啟丟失部分資料在快照方式與語句追加方式之間選擇其一,不要使用虛擬記憶體以及diskstore方式。
4.不要讓你的redis所在機器物理記憶體使用超過實際記憶體總量的3/5。
Redis使用總結
在專案開發過程中,筆主使用redis也有一段時間了。在一些特性的場景,redis能幫助我們解決一些問題。因此,總結一下分享給大家。1.使用redis實現分布式鎖 redis訪問工具類 component public class redisdao component public class red...
redis使用優化總結學習
在redis的使用中,因為其是單程序在執行,所有在實際使用的過程中因為實際情況可能經常需要進行優化。所以,蒐集了資料學習總結下。1,redis中主要的儲存方式key value模型的儲存方式,在其內部提供了多種的資料型別,可根據實際的情況使用對用的結構型別。目前發現在實際情況,基本上都是用的hash...
Redis使用總結 (序列三)
概述 1 為什麼使用redis 2 使用redis有什麼缺點 3 單執行緒的redis為什麼這麼快 4 redis的資料型別,以及每種資料型別的使用場景 5 redis的過期策略以及記憶體淘汰機制 6 redis和資料庫雙寫一致性問題 7 如何應對快取穿透和快取雪崩問題 8 如何解決redis的併發...