對於redis來講,什麼是最重要的?html
毋庸置疑,是內存。linux
redis內存使用狀況:info memoryredis
示例:算法
能夠看到,當前節點內存碎片率爲226893824/209522728≈1.08,使用的內存分配器是jemalloc。緩存
used_memory_rss 一般狀況下是大於 used_memory 的,由於內存碎片的存在。服務器
可是當操做系統把redis內存swap到硬盤時,memory_fragmentation_ratio 會小於1。redis使用硬盤做爲內存,由於硬盤的速度,redis性能會受到極大的影響。網絡
以前的文章 關於redis,你須要瞭解的幾點!中咱們簡單介紹過redis的內存使用分佈:自身內存,鍵值對象佔用、緩衝區內存佔用及內存碎片佔用。併發
redis 空進程自身消耗很是的少,能夠忽略不計,優化內存能夠不考慮此處的因素。dom
對象內存,也即真實存儲的數據所佔用的內存。高併發
redis k-v結構存儲,對象佔用能夠簡單的理解爲 k-size + v-size。
redis的鍵統一都爲字符串類型,值包含多種類型:string、list、hash、set、zset五種基本類型及基於string的Bitmaps和HyperLogLog類型等。
在實際的應用中,必定要作好kv的構建形式及內存使用預期,能夠參考 關於redis,你須要瞭解的幾點! 中關於不一樣值類型不一樣形式下的內部存儲實現介紹。
緩衝內存包括三部分:客戶端緩存、複製積壓緩存及AOF緩衝區。
1)客戶端緩存:接入redis服務器的TCP鏈接輸入輸出緩衝內存佔用,TCP輸入緩衝佔用是不受控制的,最大容許空間爲1G。輸出緩衝佔用能夠經過client-output-buffer-limit參數配置。
redis 客戶端主要分爲從客戶端、訂閱客戶端和普通客戶端。
從客戶端鏈接佔用:也就是咱們所說的slave,主節點會爲每個從節點創建一條鏈接用於命令複製,緩衝配置爲:client-output-buffer-limit slave 256mb 64mb 60。
主從之間的間絡延遲及掛載的從節點數量是影響內存佔用的主要因素。所以在涉及須要異地部署主從時要特別注意,另外,也要避免主節點上掛載過多的從節點(<=2);
訂閱客戶端內存佔用:發佈訂閱功能鏈接客戶端使用單獨的緩衝區,默認配置:client-output-buffer-limit pubsub 32mb 8mb 60。
當消費慢於生產時會形成緩衝區積壓,所以須要特別注意消費者角色配比及生產、消費速度的監控。
普通客戶端內存佔用:除了上述以外的其它客戶端,如咱們一般的應用鏈接,默認配置:client-output-buffer-limit normal 1000。
能夠看到,普通客戶端沒有配置緩衝區限制,一般通常的客戶端內存消耗也能夠忽略不計。
可是當redis服務器響應較慢時,容易形成大量的慢鏈接,主要表現爲鏈接數的突增,若是不能及時處理,此時會嚴重影響redis服務節點的服務及恢復。
關於此,在實際應用中須要注意幾點:
-> maxclients最大鏈接數配置必不可少。
-> 合理預估單次操做數據量(寫或讀)及網絡時延ttl。
-> 禁止線上大吞吐量命令操做,如keys等。
高併發應用情景下,redis內存使用須要有實時的監控預警機制,
2)複製積壓緩衝區
v2.8以後提供的一個可重用的固定大小緩衝區,用以實現向從節點的部分複製功能,避免全量複製。配置單數:repl-backlog-size,默認1M。單個主節點配置一個複製積壓緩衝區。
3)AOF緩衝區
AOF重寫期間增量的寫入命令保存,此部分緩存佔用大小取決於AOF重寫時間及增量。
關於redis,你須要瞭解的幾點!簡單介紹過redis的內存分配方式。
子進程即redis執行持久化(RDB/AOF)時fork的子任務進程。
父子進程會共享相同的物理內存頁,父進程處理寫請求時會對須要修改的頁複製一份副本進行修改,子進程讀取的內存則爲fork時的父進程內存快照,所以,子進程的內存消耗由期間的寫操做增量決定。
THP機制會下降fork子進程的速度;寫時複製內存頁由4KB增大至2M。高併發情境下,寫時複製內存佔用消耗影響會很大,所以須要選擇性關閉。
通常須要配置linux系統 vm.overcommit_memory=1,以容許系統能夠分配全部的物理內存。防止fork任務因內存而失敗。
redis的內存管理主要分爲兩方面:內存上限控制及內存回收管理。
目的:緩存應用內存回收機制觸發 + 防止物理內存用盡(redis 默認無限使用服務器內存) + 服務節點內存隔離(單服務器上部署多個redis服務節點)
在進行內存分配及限制時要充分考慮內存碎片佔用影響。
動態調整,擴展redis服務節點可用內存:config set maxmemory {}。
回收時機:鍵過時、內存佔用達到上限
1)過時鍵刪除:
redis 鍵過時時間保存在內部的過時字典中,redis採用惰性刪除機制+定時任務刪除機制。
惰性刪除:即讀時刪除,讀取帶有超時屬性的鍵時,若是鍵已過時,則刪除而後返回空值。這種方式存在問題是,觸發時機,加入過時鍵長時間未被讀取,那麼它將會一直存在內存中,形成內存泄漏。
定時任務刪除:redis內部維護了一個定時任務(默認每秒10次,可配置),經過自適應法進行刪除。
刪除邏輯以下:
】
須要說明的一點是,快慢模式執行的刪除邏輯相同,這是超時時間不一樣。
2)內存溢出控制
當內存達到maxmemory,會觸發內存回收策略,具體策略依據maxmemory-policy來執行。
noevication:默認不回收,達到內存上限,則再也不接受寫操做,並返回錯誤。
volatile-lru:根據LRU算法刪除設置了過時時間的鍵,若是沒有則不執行回收。
allkeys-lru:根據LRU算法刪除鍵,針對全部鍵。
allkeys-random:隨機刪除鍵。
volatitle-random:速記刪除設置了過時時間的鍵。
volatilte-ttl:根據鍵ttl,刪除最近過時的鍵,一樣若是沒有設置過時的鍵,則不執行刪除。
動態配置:config set maxmemory-policy {}
在設置了maxmemory狀況下,每次的redis操做都會檢查執行內存回收,所以對於線上環境,要確保所這隻的maxmemory>used_memory。
另外,能夠經過動態配置maxmemory來主動觸發內存回收。