Redis采坑(一)——數據無法插入,內存溢出


一、采坑背景

在最大數據分析的過程中,redis是被當做熱數據的緩存庫使用的,在某一天中,redis數據庫熱數據無法插入,此時數據量大概在100萬左右,很是糾結,為什么不能插入?程序的錯誤,不可能,沒有異常。redis插入數據超時,查看正常。難道是redis的配置問題,試着尋找解決方案,在網上找到了不少類似的問題,今天我們就踩一下!

二、探索問題

(一)、redis內存異常

1、我們這里模擬一下當時異常的redis環境,現在數據庫中有27條數據,大概內存占用2.4M左右,我們先把最大內存刻意設置到2M

 2、現在我們插入新的數據到redis當中

 3、查看數據總數,依舊是27條,是不是很奇怪

 (二)、redis內存恢復正常

1、現在我們將redis的內存設置到,大於現在已經使用的內存,問題即可解決

2、重新插入數據

3、數據插入后,顯示情況

到此為止,問題解決,我們是不是還有好多疑問,為什么這樣就OK了?不要急,接下來給大家分析一下!

三、內存消耗

大家都知道Redis的所有的數據都是存在了內存中的,當最大內存不足以滿足現狀的情況下,就會出現數據插入異常的情況!,如何查看Redis中內存的消耗情況哪?可以通過 info memory命令,查看Redis內存消耗的相關指標,從而有助於更好的分析內存。執行命令之后有這么幾個重要的指標:

used_memory:2515680
used_memory_human:2.40M
used_memory_rss:2478768
used_memory_rss_human:2.36M
used_memory_peak:360040528
used_memory_peak_human:343.36M
total_system_memory:0
total_system_memory_human:0B
used_memory_lua:39936
used_memory_lua_human:39.00K
maxmemory:5000000
maxmemory_human:4.77M
maxmemory_policy:noeviction
mem_fragmentation_ratio:0.99
mem_allocator:jemalloc-3.6.0

    重點需要關注下mem_fragmentation_ratio這個值:
    mem_fragmentation_ratio > 1 說明多出來的部分名沒有用於數據存儲,而是被內存碎片所消耗,相差越大,說明內存碎片率越嚴重。
    mem_fragmentation_ratio < 1 一般出現在Redis內存交換(Swap)到硬盤導致(used_memory > 可用最大內存時,Redis會把舊的和不適用的數據寫入到硬盤,這塊空間就叫Swap空間),出現這種情況需要格外關注,硬盤速度遠遠慢於內存,Redis性能就會變得很差,甚至僵死。

(一)、內存消耗的划分
    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),父子進程會共享相同的物理內存頁,當父進程寫請求時會對需要修改的頁復制出一份副本來完成寫操作。

 四、管理內存

 (一)設置上限
    Redis默認是無限使用內存。所以在使用的時候盡量的去配置maxmemory,給Redis設置內存使用上限,防止因Redis的無限使用造成系統內存耗盡。有一點需要注意的是maxmemory配置的是Redis實際使用的內存量,即used_memory,由於有內存碎片的存在,所以實際的內存使用比used_memory要大。
    Redis可以動態的執行內存的調整:

config set maxmemory 6GB

 (二)配置內存回收策略
    Redis的內存回收機制主要體現在兩個方面上:
    對過期數據的處理
    當內存使用情況達到maxmemory時觸發內存回收策略
    1. 過期鍵的刪除
    惰性刪除:什么時候執行呢?就是在客戶端讀取帶有超時屬性的鍵時,如果已經超過鍵值設置的過期時間,則刪除並返回空。這樣做的目的主要是為了節省CPU成本考慮,不需要單獨維護TTL鏈表來處理過期鍵的刪除。但是,如果單獨使用這種方式存在一個問題,如果當前的鍵值永遠不再被訪問呢?就不刪除了嗎?那肯定不行,這就會造成內存泄漏的問題。那Redis是怎么解決的呢?Redis提供了一個定時任務的刪除機制來做補充。
    2. 定時任務刪除
    Redis內部維護了一個定時任務,默認是每秒運行十次。刪除的邏輯如下圖:
這里寫圖片描述
    
    3.內存溢出控制策略
    當Redis使用的內存達到上限maxmemory后,就會根據maxmemory-policy設置的相關策略進行對應的操作,Redis支持一下6中策略:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM