[緩存系列] redis那點事

iagme.png

本文,你將閱讀到以下內容:

  • 如何應對緩存擊穿和緩存雪崩的問題;
  • Redis 的過期策略以及內存淘汰機制;

1.如何應對緩存擊穿和緩存雪崩的問題?
  • 場景:在大并發情況下,流量幾百萬左右;

  • 概念:

    • 緩存穿透:故意去請求緩存中不存在的數據,導致所有的請求都懟到數據庫上,然而數據庫中也不存在,直接返回null,要是有人利用不存在的key頻繁攻擊我們的應用,那就有可能造成數據庫的崩潰;
    • 緩存雪崩:設置緩存時采用了相同的過期時間,導致緩存在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩;
    • 緩存擊穿:緩存中的某一個key在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的并發請求過來,這些請求發現緩存過期一般都會從后端DB加載數據并回設到緩存,這個時候大并發的請求可能會瞬間把后端DB壓垮;
  • 解決:

    • 緩存穿透 or 緩存擊穿解決方案
      • 布隆過濾器:將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力;
      • 緩存null值:如果一個查詢返回的數據為空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
    • 緩存雪崩解決方案:
      • 緩存失效時間分散開來:可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件;
      • 使用互斥鎖(該方案吞吐量明顯會下降):用加鎖或者隊列的方式保證緩存的單線 程(進程)寫,從而避免失效時大量的并發請求落到底層存儲系統上;
      • 雙緩存:設計兩個緩存,緩存A和緩存B,緩存A的設置過期時間,緩存B不設失效時間,自己做緩存預熱操作;(可以細分下設計:從緩存A 讀數據,有則直接返回;A沒有數據,直接從B讀數據,直接返回,并且異步啟動一個更新線程,更新線程同時更新緩存A和緩存B);
2.Redis 的過期策略以及內存淘汰機制
  • 場景:
    比如你的Redis只能存5G數據,可是你寫了10G,那會刪5G的數據,怎么刪的? 這個問題思考過么?
    或者,你的數據已經設置了過期時間,但是時間到了,內存占用率還是比較高,有思考過原因么?

  • 概念

    • 被動刪除:用到的時候才會去檢驗key是不是已過期,過期就刪除;
    • 主動刪除:Redis會定期主動淘汰一批已過去的key;
  • 原因:

    • 定時刪除(主動刪除)
      • 含義:在設置key的過期時間的同時,為該key創建一個定時器,讓定時器在key的過期時間來臨時,對key進行刪除;
      • 優點:保證內存被盡快釋放;
      • 缺點:若過期key很多,刪除這些key會占用很多的CPU時間,在CPU時間緊張的情況下,CPU不能把所有的時間用來做要緊的事兒,還需要去花時間刪除這些key定時器的創建耗時,若為每一個設置過期時間的key創建一個定時器(將會有大量的定時器產生)性能影響嚴重沒人用;
    • 定期刪除(主動刪除)
      • 含義:每隔一段時間執行一次刪除(在redis.conf配置文件設置hz,1s刷新的頻率)過期key操作
      • 優點:通過限制刪除操作的時長和頻率,來減少刪除操作對CPU時間的占用--處理"定時刪除"的缺點定期刪除過期key--處理"惰性刪除"的缺點.
      • 缺點:在內存友好方面,不如"定時刪除"在CPU時間友好方面,不如"惰性刪除"
      • 難點:合理設置刪除操作的執行時長(每次刪除執行多長時間)和執行頻率(每隔多長時間做一次刪除)這個要根據服務器運行情況來定了.
    • 惰性刪除(被動刪除)
      • 含義:key過期的時候不刪除,每次從緩存中獲取key的時候去檢查是否過期,若過期,則刪除,返回null。
      • 優點:刪除操作只發生在從數據庫取出key的時候發生,而且只刪除當前key,所以對CPU時間的占用是比較少的,而且此時的刪除是已經到了非做不可的地步(如果此時還不刪除的話,我們就會獲取到了已經過期的key了)
      • 缺點:若大量的key在超出超時時間后,很久一段時間內,都沒有被獲取過,那么可能發生內存泄露(無用的垃圾占用了大量的內存);
  • 過期策略配置

    • redis 內部默認采用的是定期刪除+惰性刪除策略;
      • 定期刪除+惰性刪除流程:
        • 惰性刪除流程:在進行get或setnx等操作時,先檢查key是否過期,若過期,刪除key,然后執行相應操作;若沒過期,直接執行相應操作;
        • 定期刪除流程:遍歷每個數據庫(就是redis.conf中配置的"database"數量,默認為16),循環遍歷當前庫中的指定個數個key(默認是每個庫檢查20個key),如果當前庫中沒有一個key設置了過期時間,直接執行下一個庫的遍歷,隨機獲取一個設置了過期時間的key,檢查該key是否過期,如果過期,刪除key.判斷定期刪除操作是否已經達到指定時長(配置redis.conf 的hz選項),若已經達到,直接退出定期刪除. 也可以通過配置redis.conf的maxmemory最大值,當已用內存超過maxmemory限定時,就會觸發定期刪除策略;
    • 過期key對持久化RDB和AOF的影響
      • 從內存數據庫持久化數據到RDB文件,持久化key之前,會檢查是否過期,過期的key不進入RDB文件;
      • 從RDB文件恢復數據到內存數據庫,在數據載入內存數據庫之前,會對key先進行過期檢查,如果過期,不導入數據庫.
      • 從內存數據庫持久化數據到AOF文件,當key過期后,還沒有被刪除時,此時進行執行持久化操作(該key是不會進入aof文件的,因為沒有發生修改命令).
      • 當key過期后,在發生刪除操作時,程序會向aof文件追加一條del命令(在將來的以aof文件恢復數據的時候該過期的鍵就會被刪掉);
      • AOF重寫時,會先判斷key是否過期,已過期的key不會重寫到aof文件.
    • 采用定期刪除+惰性刪除就沒其他問題了么?
      • 并不是這樣的,如果定期刪除沒刪除Key,然后你也沒即時去請求Key,也就是說惰性刪除也沒生效.這樣,Redis的內存會越來越高.那么就應該采用內存淘汰機制.
  • 內存淘汰機制

    • 原因:Redis內存淘汰指的是用戶存儲的一些鍵被可以被它主動地從實例中刪除,從而產生讀miss的情況,內存的淘汰機制的初衷是為了更好地使用內存,用一定的緩存miss來換取內存的使用效率;
    • 配置:
      • Redis內存淘汰通過配置redis.conf中的maxmemory這個值來開啟,maxmemory為0的時候表示我們對Redis的內存使用沒有限制;
      • 淘汰策略的選擇可以通過redis.conf中的maxmemory-policy來配置;
      • 主鍵空間 && 設置了過期時間的鍵空間:在redis中,如果有一批鍵存儲在Redis中,則有那么一個哈希表用于存儲這批鍵及其值,如果這批鍵中有一部分設置了過期時間,那么這批鍵還會被存儲到另外一個哈希表中.設置了過期時間的鍵空間為主鍵空間的子集。
    • 淘汰策略:
      • noeviction:當redis內存數據達到maxmemory,在該策略下,新寫入數據時直接返回OOM錯誤;
      • allkeys-lru:當內存不足以容納新寫入數據時,在主鍵空間中,優先移除最近未使用的一些key[以配置文件中的maxmemory-samples個key作為樣本池進行抽樣清理];
      • allkeys-random:當內存不足以容納新寫入數據時,在主鍵空間中,隨機移除某些key[以配置文件中的maxmemory-samples個key作為樣本池進行抽樣清理];
      • volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key[以配置文件中的maxmemory-samples個key作為樣本池進行抽樣清理],這種情況一般是把redis既當緩存,又做持久化存儲的時候才用.
      • volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某些key.
      • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key[以配置文件中的maxmemory-samples個key作為樣本池進行抽樣清理]優先移除;
    • 注意:
      • 淘汰策略的清理過程是阻塞的,直到清理出足夠的內存空間.所以如果在達到maxmemory并且調用方還在不斷寫入的情況下,可能會反復觸發主動清理策略,導致請求會有一定的延遲.
      • 盡量不要觸發maxmemory,最好在mem_used內存占用達到maxmemory的一定比例后,需要考慮調大hz以加快淘汰,或者進行集群擴容.
      • 如果能夠控制住內存,則可以不用修改maxmemory-samples配置;如果Redis本身就作為LRU cache服務(這種服務一般長時間處于maxmemory狀態,由Redis自動做LRU淘汰),可以適當調大maxmemory-samples.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容