目錄
1、內存上限介紹
1.1、產生原因
1.2、Redis的maxmemory限額
1.3、影響的命令與場景
2.?內存用完后的策略
2.1、淘汰策略分類
2.2、淘汰策略介紹
2.3、不同策略對比
3、常見業務示例
3.1、影響
3.2、監控與自動告警
前言
????????在日常項目中,不知道你思考過沒有redis的內存耗盡的情況?
如下所示:
具體行為:
當內存滿時:
- 讀操作(如GET):可以正常進行
- 寫操作(如SET、LPUSH、SADD等):
- 如果能通過淘汰策略釋放一點空間,則寫入繼續
- 如果根據策略無法再釋放空間(比如noeviction),則直接返回錯誤:“OOM command not allowed when used memory > 'maxmemory'.”
風險:
- 如果是noeviction(默認),Redis直接拒絕寫入!
- 如果淘汰策略被觸發,你的“舊數據”就會被自動刪除(可能有業務風險)。
- 內存頁碎片、fork快照等也會加速內存耗盡。
- 極端情況下,如果宿主機內存被撐爆,系統可能直接kill掉Redis進程(OOM Killer)。
關于更多redis的介紹,可參考:對Redis組件的深入探討_redis 磁盤 內存-CSDN博客文章瀏覽閱讀1.3k次,點贊20次,收藏8次。前言在介紹redis的時候,先介紹下存儲介質,磁盤和內存。通過對以下兩種認識,對了解redis有著更深的理解。如下圖所示:以上就是r。_redis 磁盤 內存https://blog.csdn.net/weixin_50055999/article/details/147757520?spm=1011.2415.3001.5331
1、內存上限介紹
????????Redis是內存數據庫,所有數據(Key/Value)都存放在內存(RAM)中,不像MySQL等主要用磁盤。
Redis的數據結構不僅要存儲你的 key/value 數據,還要存儲:
1、Key/value 相關的元數據(如過期信息)
2、Append Only File (AOF)
3、緩沖區復制緩沖區、客戶端連接緩沖區等
所以實際內存消耗 = 數據+各種維護數據+內存碎片。
1.1、產生原因
1、數據總量超過maxmemory配置:
這是最常見情況:寫入、緩存、業務量上漲、沒有刪除機制,累計到了上限。
2、未設置maxmemory,Redis自動用光了系統全部內存:
系統會自動kill Redis進程(Linux OOM Killer)。
3、AOF或RDB備份引起內存瞬時暴漲:
快照/流復制/fork過程占用大量額外內存。
4、客戶端緩沖區、復制緩沖區太大:
有些命令或者慢客戶端導致緩沖區堆積。
5、內存碎片率很高:
內存并不是100%利用,碎片率過高也會導致出現“看似還有容量,實際已用盡”的問題。
1.2、Redis的maxmemory限額
Redis 是基于內存的數據庫,其總內存上限可通過maxmemory參數配置。
比如在redis.conf中:
maxmemory 1gb
如果你沒有設置,理論上 Redis 可以用光宿主機所有可用內存,直到被Linux OOM殺死進程。
1.3、影響的命令與場景
1、影響所有產生新內存分配的命令
包括:set/hash/set/zset/list的增量寫入命令,bitmap、hyperloglog…
2、以下命令不會報錯
讀命令(GET/EXISTS/SCAN等)
刪除命令(DEL/EXPIRE/UNLINK)
清空命令(FLUSHDB、FLUSHALL)
2.?內存用完后的策略
????????當 Redis 達到?maxmemory?限制(即內存“用完”),會按照配置的淘汰策略(maxmemory-policy參數)來處理新寫入命令。
如下圖所示:
寫請求 -> 檢查used_memory|是否超maxmemory?/ \否 是| |正常寫 執行淘汰策略|能釋放內存嗎?/ \能 不能| |正常寫 返回OOM錯誤,寫失敗
2.1、淘汰策略分類
- noeviction(默認):不淘汰,拒絕寫入,只允許讀;
- allkeys-lru:將所有key中最久未使用的key淘汰;
- volatile-lru:只對設置了過期時間的key做lru淘汰;
- allkeys-random:所有key隨機淘汰;
- volatile-random:只對設置了過期的key隨機淘汰;
- volatile-ttl:優先淘汰過期時間到期最早的key;
- volatile-lfu、allkeys-lfu:最不常用的(Least Frequently Used)key被淘汰。
2.2、淘汰策略介紹
1、noeviction(默認)
只讀不寫:?所有新增key、修改key、增加元素的命令(如SET、LPUSH、HSET等) 統統返回錯誤(error),只允許讀(GET等)。
(error) OOM command not allowed when used memory > 'maxmemory'.
- 危險:
- 業務寫入完全中斷
- 可能造成數據庫/隊列/秒殺等核心數據業務丟失
- 生產極其危險,尤其是做緩存穿透時容易擊穿下游數據庫
2、allkeys-lru
自動淘汰:?
????????優先淘汰“最久未使用”的key(Least Recently Used),騰出空間讓新數據寫成功。
風險:
????????部分“冷數據”被自動刪掉,新數據繼續寫入,服務不中斷,但有可能丟掉了有用的老數據。
3、volatile-lru
- 只判斷有過期時間(expire)的key。
- 只淘汰帶過期時間的key,不帶過期屬性的key永遠不會被刪
- 如果全是永久key,效果跟noeviction一樣,容易寫不進去
4、allkeys-random/volatile-random
- allkeys-random:任意key隨機淘汰。
- volatile-random:也只淘汰帶過期的key,隨機選擇。
5、volatile-ttl
只淘汰帶過期時間里“快要到期”的key。
6、allkeys-lfu/volatile-lfu
淘汰最少被訪問的key(Least Frequently Used),更智能。
2.3、不同策略對比
如下所示:
注意:
- 持久化(RDB/AOF)也有可能被影響,如果沒法持久化新數據,有可能異常或數據丟失!
- 主從同步、集群等同步數據也受maxmemory影響。
3、常見業務示例
3.1、影響
1、緩存:
????????如果用作普通緩存,可以用allkeys-lru/allkeys-lfu讓Redis自動“以空間換時間”。熱點數據永遠在,冷數據慢慢淘汰,更健康。
2、持久化隊列/核心計數/實時業務:
? ? ? ? 如果Redis用作數據庫功能(存放業務數據、消費隊列),noeviction策略推薦。避免關鍵數據被誤刪。一旦寫入超限應報警、擴容、限流,絕不隨便丟“老數據”。
3、大key、熱key、慢客戶端
某個大key占住大量內存,會加速爆表,需依據業務定期分析優化。
更多bigkey文章介紹,參考:
Redis中的bigkey的介紹及影響_redis 大key-CSDN博客文章瀏覽閱讀1.2k次,點贊31次,收藏12次。什么是BigKey?為什么它成為Redis的性能殺手?BigKey指在Redis中key對應的value占用內存或元素數量超出業務合理閾值的鍵值對。_redis 大keyhttps://blog.csdn.net/weixin_50055999/article/details/148856033?spm=1011.2415.3001.5331
4、內存暴漲瞬間寫崩潰
? ? ? ?新增了超大key(如bitmap、大string、大list),遠超單條key的預期,會導致寫入命令的突然異常或長時間阻塞(尤其fork的時候)。
3.2、監控與自動告警
建議配合運維/監控工具(如Prometheus、Grafana、redis_exporter、阿里云/騰訊云云監控等)。
重點關注:
1、used_memory (info memory)。
2、maxmemory。
3、內存碎片率。
4、淘汰計數器evicted_keys。
5、命令拒絕計數rejected_connections。
總結
????????Redis的內存滿了,不同的淘汰策略決定要不要丟棄已有數據騰空間,否則直接拒絕寫入并報錯,只能讀不能寫,業務必須配合好監控、限流和數據結構優化。
參考文章:
1、內存耗盡后,Redis會發生什么?_redis中key沒有達到過期時間,但是內存滿了會怎么樣?-CSDN博客文章瀏覽閱讀84次。作為一臺服務器來說,內存并不是無限的,所以總會存在內存耗盡的情況,那么當 Redis 服務器的內存耗盡后,如果繼續執行請求命令,Redis 會如何處理呢?_redis中key沒有達到過期時間,但是內存滿了會怎么樣?https://blog.csdn.net/qq_30987095/article/details/143257130?ops_request_misc=%257B%2522request%255Fid%2522%253A%252295fab89f19b3cb10a23ea7030593bb32%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=95fab89f19b3cb10a23ea7030593bb32&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-143257130-null-null.142^v102^control&utm_term=redis%E5%86%85%E5%AD%98%E8%80%97%E5%B0%BD&spm=1018.2226.3001.4187