Redis深刻學習筆記(六)Redis內存分配

Redis的高效能夠說是輕量級的epoll模型和基於內存的讀寫共同組成的,關於epoll對於之前的select或者poll的性能優點這裏不作介紹,本篇主要介紹領一個重點,Redis的內存分配原理。安全

獲取內存信息命令:info memory服務器

used_memory:  Redis分配器分配的內存總量,就是內部存儲的全部數據內存佔用量。        網絡

used_memory_human:  以可讀的格式返回used_memory。架構

used_memory_rss:  以操做系統同的角度顯示Redis進程佔用的物理內存總量。  性能

used_memory_rss_human:  以可讀的格式返回used_memory_rss。lua

used_memory_peak:  內存使用的峯值。spa

used_memory_peak_human:  以可讀的格式返回used_memory_peak。操作系統

total_system_memory:  系統可用內存總量。3d

total_system_memory_human:  以可讀的格式返回total_system_memory。對象

used_memory_lua:  lua引擎消耗的內存總量。

used_memory_lua_human:  以可讀的格式返回used_memory_lua。

maxmemory:  Redis最大可用內存。

maxmemory_human:  以可讀的格式返回maxmemory。

maxmemory_policy:  達到最大可用內存時使用的淘汰策略。

mem_fragmentation_ratio:  used_memory_rss/used_memory比值,標識碎片率。

mem_allocator:  Redis使用的內存分配器,默認是jemalloc。

  重要指標:used_memory_rss和used_memory以及它們的比值mem_fragmentation_ratio。

  當mem_fragmentation_ratio>1時,說明used_memory_rss-used_memory多出的部份內存並無用於數據存儲,而是被內存碎片所消耗,若是二者相差很大,說明碎片率嚴重。

  當mem_fragmentation_ratio<1時,這種狀況通常出如今操做系統把Redis內存交換(Swap)到硬盤致使,出現這種狀況時要格外關注,因爲硬盤速度遠遠慢於內存,Redis性能會變得不好,甚至僵死。

內存分配圖:

自身內存:Redis運行自身使用的內存

對象內存:用戶數據

緩衝內存:客戶端緩衝、複製積壓緩衝區、AOF緩衝區

 

  客戶端緩衝:指的是全部接入到Redis服務器TCP鏈接的輸入輸出緩衝。輸入緩衝沒法控制,最大空間爲1G,若是超過將斷開鏈接。輸出緩衝經過參數client-output-buffer-limit控制。輸入輸出緩衝區在大流量的場景中容易失控,形成Redis內存的不穩定,須要重點監控。

    普通客戶端:除了複製和訂閱的客戶端以外的全部鏈接,Redis的配置項是:client-output-buffer-limit。Redis並無對普通客戶端的輸出緩衝區作限制,通常普通客戶端的內存消耗能夠忽略不計,可是當有大量慢鏈接客戶端接入時這部份內存消耗就不能忽略了,能夠設置maxclients作限制。特別是當使用大量數據輸出的命令且數據沒法及時推送給客戶端時,如monitor命令,容易形成Redis服務器內存忽然飆升。

    從客戶端:主節點會爲每一個從節點單獨創建一條鏈接用於命令複製,配置項是:client-output-buffer-limit。當主從節點之間網絡延遲較高或主節點掛載大量從節點時這部份內存消耗將佔用很大一部分,建議主節點掛載的從節點不要多於2個,主從節點不要部署在較差的網絡環境下,如異地跨機房環境,防止複製客戶端鏈接緩慢形成溢出。

    訂閱客戶端:當使用發佈訂閱功能時,鏈接客戶端使用單獨的輸出緩衝區,配置項爲:client-output-buffer-limit,當訂閱服務的消息生產快於消費速度時,輸出緩衝區會產生積壓形成輸出緩衝區空間溢出。  

 

  複製積壓緩衝區:Redis在2.8版本以後提供了一個可重用的固定大小緩衝區用於實現部分複製功能,根據repl-backlog-size參數控制,默認1MB。對於複製積壓緩衝區整個主節點只有一個,全部的從節點共享此緩衝區,所以能夠設置較大的緩衝區空間,如100MB,這部份內存投入是有價值的,能夠有效避免全量複製。

 

  AOF緩衝區:這部分空間用於在Redis重寫期間保存最近的寫入命令。AOF緩衝區空間消耗用戶沒法控制,消耗的內存取決於AOF重寫時間和寫入命令量,這部分空間佔用一般很小。

 

內存碎片:

  Redis默認的內存分配器採用jemalloc,在64位系統中將內存空間劃分爲:小、大、巨大三個範圍。每一個範圍內又劃分爲多個小的內存塊單位,以下所示:

  小:[8byte],[16byte,32byte,48byte,...,128byte],[192byte,428256byte,...,512byte],[768byte,1024byte,...,3840byte]

  大:[4KB,8KB,12KB,...,4072KB]

  巨大:[4MB,8MB,12MB,...]

  大量過時鍵刪除,鍵對象過時刪除後,釋放的空間沒法獲得充分利用,致使碎片率上升。重啓節點能夠作到內存碎片從新整理,所以能夠利用高可用架構,如Sentinel或Cluster,將碎片率太高的主節點轉換爲從節點,進行安全重啓。

 

子進程內存消耗:

  子進程內存消耗主要指執行AOF/RDB重寫時Redis建立的子進程內存消耗。Redis執行fork操做產生的子進程內存佔用量對外表現爲與父進程相同,理論上須要一倍的物理內存來完成重寫操做。但Linux具備寫時複製技術(copy-on-write),父子進程會共享相同的物理內存頁,當父進程處理寫請求時會對須要修改的頁複製出一份副本完成寫操做,而子進程依然讀取fork時整個父進程的內存快照。

  Linux Kernel在2.6.38內核增長了Transparent Huge Pages(THP)機制,而有些Linux發行版即便內核達不到2.6.38也會默認加入並開啓這個功能,如Redhat Enterprise Linux在6.0以上版本默認會引入THP。雖然開啓THP能夠下降fork子進程的速度,但以後copy-on-write期間複製內存頁的單位從4KB變爲2MB,若是父進程有大量寫命令,會加劇內存拷貝量,從而形成過分內存消耗。

  子進程內存消耗須要注意:

    Redis產生的子進程並不須要消耗1倍的父進程內存,實際消耗根據期間寫入命令量決定,可是依然要預留出一些內存防止溢出。

    須要設置sysctl vm.overcommit_memory=1容許內核能夠分配全部的物理內存,防止Redis進程執行fork時因系統剩餘內存不足而失敗。

    排查當前系統是否支持並開啓THP,若是開啓建議關閉,防止copy-on-write期間內存過分消耗。

 

 

下一篇會介紹Redis不一樣類型對象的存儲和管理

相關文章
相關標籤/搜索