1、內存消耗 |
如何查看Redis中內存的消耗情況哪?可以通過 info
命令,查看Redis內存消耗的相關指標,從而有助於更好的分析內存。執行命令之後有這麼幾個重要的指標:
屬性名 | 屬性說明 |
---|---|
used_memory |
Redis分配器分配的內存總量,指Redis存儲的所有數據所佔的內存 |
used_memory_human |
以可讀的形式返回user_memory |
used_memory_rss |
Redis進程佔用的物理內存總量 |
used_memory_peak |
used_memory 使用的峯值 |
used_memory_peak_human |
可讀格式返回used_memory_peak |
used_memory_lua |
Lua引擎消耗的內存大小 |
mem_fragmentation_ratio |
used_memory_rss /used_memory 比值,內存碎片率 |
mem_allocator |
Redis所使用的內存分配器,默認jemalloc |
used_memory:1038744104
used_memory_human:990.62M
used_memory_rss:5811122176
used_memory_peak:4563077088
used_memory_peak_human:4.25G
used_memory_lua:35840
mem_fragmentation_ratio:5.59
mem_allocator:libc
重點需要關注下mem_fragmentation_ratio
這個值:
mem_fragmentation_ratio > 1
說明多出來的部分名沒有用於數據存儲,而是被內存碎片所消耗,相差越大,說明內存碎片率越嚴重。
mem_fragmentation_ratio < 1
一般出現在Redis內存交換(Swap)到硬盤導致(used_memory > 可用最大內存
時,Redis會把舊的和不適用的數據寫入到硬盤,這塊空間就叫Swap空間),出現這種情況需要格外關注,硬盤速度遠遠慢於內存,Redis性能就會變得很差,甚至僵死。
1.1、內存消耗的劃分 |
Redis的內存主要包括:對象內存+緩衝內存+自身內存+內存碎片。
1、對象內存
對象內存是Redis內存中佔用最大一塊,存儲着所有的用戶的數據。Redis所有的數據都採用的是key-value型數據類型,每次創建鍵值對的時候,都要創建兩個對象,key對象和value對象。key對象都是字符串,value對象的存儲方式,五種數據類型–String,List,Hash,Set,Zset。每種存儲方式在使用的時候長度、數據類型不同,則佔用的內存就不同。
2、緩衝內存
主要包括:客戶端緩衝、複製積壓緩衝區、AOF緩衝區
客戶端緩衝:普通的客戶端的連接(大量連接),從客戶端(主要是複製的時候,異地跨機房,或者主節點下有多個從節點),訂閱客戶端(發佈訂閱功能,生產大於消費就會造成積壓)
複製積壓緩衝:2.8版本之後提供的可重用的固定大小緩衝區用於實現部分複製功能,默認1MB,主要是在主從同步時用到。
AOF緩衝區:持久化用的,會先寫入到緩衝區,然後根據響應的策略向磁盤進行同步,消耗的內存取決於寫入的命令量和重寫時間,通常很小。
3、內存碎片
目前可選的分配器有jemalloc、glibc、tcmalloc默認jemalloc
出現高內存碎片問題的情況:大量的更新操作,比如append、setrange;大量的過期鍵刪除,釋放的空間無法得到有效利用
解決辦法:數據對齊,安全重啓(高可用/主從切換)。
4、自身內存
主要指AOF/RDB重寫時Redis創建的子進程內存的消耗,Linux具有寫時複製技術(copy-on-write),父子進程會共享相同的物理內存頁,當父進程寫請求時會對需要修改的頁複製出一份副本來完成寫操作。
2、管理內存 |
設置上限
Redis默認是無限使用內存。所以在使用的時候儘量的去配置maxmemory
,給Redis設置內存使用上限,防止因Redis的無限使用造成系統內存耗盡。有一點需要注意的是maxmemory
配置的是Redis實際使用的內存量,即used_memory
,由於有內存碎片的存在,所以實際的內存使用比used_memory
要大。
Redis可以動態的執行內存的調整:
config set maxmemory 6GB
配置內存回收策略
Redis的內存回收機制主要體現在兩個方面上:
對過期數據的處理
當內存使用情況達到maxmemory時觸發內存回收策略
1. 過期鍵的刪除
惰性刪除:什麼時候執行呢?就是在客戶端讀取帶有超時屬性的鍵時,如果已經超過鍵值設置的過期時間,則刪除並返回空。這樣做的目的主要是爲了節省CPU成本考慮,不需要單獨維護TTL鏈表來處理過期鍵的刪除。但是,如果單獨使用這種方式存在一個問題,如果當前的鍵值永遠不再被訪問呢?就不刪除了嗎?那肯定不行,這就會造成內存泄漏的問題。那Redis是怎麼解決的呢?Redis提供了一個定時任務的刪除機制來做補充。
2. 定時任務刪除
Redis內部維護了一個定時任務,默認是每秒運行十次。刪除的邏輯如下圖:
內存溢出控制策略
當Redis使用的內存達到上限maxmemory
後,就會根據maxmemory-policy
設置的相關策略進行對應的操作,Redis支持一下6中策略:
策略 | 說明 |
---|---|
noeviction |
默認策略,不會刪除任何數據,拒絕所有寫入操作並返回客戶端錯誤信息(error)OOM command not allowed when used memory |
volatile-lru |
只對設置有超時屬性的Key根據LRU算法執行刪除操作,如果沒有可刪除的Key,則回退到noeviction 策略 |
allkeys-lru |
針對所有的key,根據LRU算法執行刪除操作直到回收到足夠內存空間 |
allkeys-random |
隨機刪除所有的鍵,直到騰出足夠空間 |
volatile-random |
針對帶有過期屬性的鍵,進行刪除操作,直到騰出足夠空間 |
volatile-ttl |
根據鍵值對象的ttl屬性,刪除最近將要過期數據。如果沒有,則回退到noviction策略 |