理解Redis的內存回收機制和過期淘汰策略

 redis回收機制 | 過期淘汰

Hello,大家好。我是公衆號 “八點半技術站” 的創作者 - Bruce.D。

今天是週二(2020-06-17),分享一句諺語 “讀書有三到,心到口到眼到” 分享給大家的是 「緩存服務 模塊」- 理解Redis的內存回收機制和過期淘汰策略

歡迎熱愛 IT編程的各位精英,歡迎進入wechat技術羣(底部有二維碼)一起交流成長

花幾分鐘時間去瀏覽 redis 技術乾貨,或許對你有用!!!

底部有本篇文章的思維導圖 ,供大家收藏使用~~~

01

今天寫這篇文章的靈感,來自之前一位好友投稿的面試題:redis 的過期策略有哪些?內存淘汰機制有哪些?我將工作中遇到的問題分析,整理成一篇文章提供大家學習,希望對大家有所幫助。

我們從一次廣告數據問題說起:一個依賴定時器任務的生成接口數據,有時候會有,有時候沒有。

然後我們分析應該是redis過期刪除策略導致。

排查過程中,因爲手動執行定時器,set數據沒有報錯,但是set後不生效。這就狠尷尬。

發現,set 沒有報錯,但是 set 完畢在查的情況下,發現沒有數據。開始懷疑 redis 的過期策略(準確來說應該是 redis 的內存回收機制中的數據淘汰策略觸發內存上限淘汰數據),導致新加入的的redis的數據都被丟棄了。

最終發現故障是因爲配置問題,導致數據錯誤。(有時候也會因爲內存滿)

在這裏我主要希望大家明白,我們遇到類似問題,如何有效證明正確性,以及什麼情況下懷疑內存回收纔是合理,所以內存回收機制的一系列問題,你也要知道了解。

02

Q:爲什麼需要內存回收?

A:第一種:在redis 中,set 指令可以指定 key 的過期時間,當過期時間達到以後,key 就會失效。

第二種:redis 是基於內存操作的,所有的數據都是保存在內存中,一臺機器的內存是很寶貴的。

分析:根據以上這倆種,爲了保證 redis 提供有效可靠的服務,redis 需要一種機制清理不常用的、無效的、多餘的數據,失效後的數據需要及時清理,這就需要內存回收

03

redis 的內存回收主要分爲:過期刪除策略 與 內存淘汰策略 倆部分。

過期刪除策略:刪除到達過期時間的 key 。(過期刪除策略原理 - 結合文章,百度自行搜索)

第一種:定時刪除

對於每一個設置了過期時間的 key 都會創建一個定時器,一旦達到過期時間都會刪除。這種方式立即清除過期數據,對內存比較好,

但是有缺點是:佔用了大量 CPU 的資源去處理過期數據,會影響 redis 的吞吐量 和 響應時間。 

第二種:惰性刪除

當訪問一個 key 的時候,纔會判斷該 key 是否過期,如果過期就刪除。該方式能最大限度節省 CPU 的資源。

但是對內存不太好,有一種比較極端的情況:出現大量的過期 key 沒有被再次訪問,因爲不會被清除,導致佔用了大量的內存。

第三種:定期刪除

每隔一段時間,掃描redis 中過期key 的字典,並清除部分過期的key。這種方式是前倆種一種折中方法。

不同的情況下,調整定時掃描時間間隔,讓CPU 與 內存達到最優。

內存淘汰策略:redis 內存淘汰策略是指達到maxmemory極限時,使用某種算法來決定來清理哪些數據,以保證新數據存入。(原理同上)

redis的內存淘汰機制分爲:

(1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。

(2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)。

(3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key。

(4)volatile-lru當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 key。

(5)volatile-random當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 key。

(6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 key 優先移除。

04

總結:看完這些,我們得知道一點,如何證明故障不是由於內存回收機制引起的?

根據上述分析,set 沒有報錯,但是不生效,那麼就2種情況:

(1)設置過期時間過短

(2)內存超過最大限制,且設置的是noeviction或者allkeys-random

因此,在遇到這種情況,首先看set的時候是否加了過期時間,且過期時間是否合理,如果過期時間較短,那麼應該檢查一下設計是否合理。

如果過期時間沒問題,那就需要查看Redis的內存使用率,查看Redis的配置文件或者在Redis中使用info命令查看Redis的狀態,maxmemory屬性查看最大內存值。

如果是0,則沒有限制,此時是通過total_system_memory限制,對比used_memory與Redis最大內存,查看內存使用率。

如果當前的內存使用率較大,那麼就需要查看是否有配置最大內存,如果有且內存超了,那麼就可以初步判定是內存回收機制導致key設置不成功,還需要查看內存淘汰算法是否noeviction或者allkeys-random.

如果是,則可以確認是redis的內存回收機制導致。

如果內存沒有超,或者內存淘汰算法不是上面的兩者,則還需要看看key是否已經過期,通過ttl查看key的存活時間。

如果運行了程序,set沒有報錯,則ttl應該馬上更新,否則說明set失敗,如果set失敗了那麼就應該查看操作的程序代碼是否正確了。

全文思維導圖:

恭喜你,又讀完了一篇文章。

在這裏,希望你看完的 每篇文章 都能對自己有所提升(哪怕是幫助你再次鞏固記憶)。

微信 : xzzs730(長按左側二維碼添加)

技術交流羣:備註技術

PHP|WEB|Java面試羣:備註面試

商務合作:gtcarry888

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章