Redis中幾個簡單的概念:緩存穿透/擊穿/雪崩,別再被嚇唬了


 

Redis中幾個“看似”高大上的概念,經常有人提到,某些好事者喜歡死扣概念,實戰沒多少,嘴巴里冒出來的全是高大上的名詞,個人一向鄙視概念黨,呵呵!

其實這幾個概念:緩存穿透/緩存擊穿/緩存雪崩,有一個共通的相似之處,就是高並發下,某些原因導致緩存層失去了保護,導致后端的持久化層(數據庫)承擔較大壓力的情形。
需要注意的是,這些問題發生的前提,需要有足夠大的並發性,如果本身並發性不高,那些即便出現了這些個問題,也不會造成非常大的影響。
甚至極端地講,只要代碼的健壯性足夠,即便是緩存層全部宕機,也不會導致整個應用程序的崩潰,只不過是所有的請求都指向后端的持久化數據庫層罷了。
試問,排出一些低級的問題包括方案,君見過多少請求壓垮數據庫的場景,或者數據緩存流行之前應用程序就應付不了高並發?
使用緩存,更多的進一步改善性能或者並發,而不是因為數據庫被壓垮了才使用緩存。

緩存穿透
緩存穿透本質上是查詢一個緩存和數據庫中都不存在的key值,Redis的緩存層無法命中,導致請求再次指向執行數據庫層的情況。
由於是查詢到值不存在(當然也不存在與Redis緩存中),導致請求總是“穿透”Redis發往數據庫層,因此緩存層失去了“保護”關系數據庫層的意義。
解決方案:
布隆過濾器是一個比較好的選擇,參考:https://www.cnblogs.com/wy123/p/11571215.html

緩存擊穿
強調對於某些熱點key,緩存穿透本質上是高並發地請求一個緩存中不存在,但是數據庫中存在的key值,導致並發請求指向數據庫,導致數據庫端承擔大量的請求壓力的情況,本質上跟緩存穿透一樣。
主要側重的是並發&&“熱點”Key不存在與緩存中,導致請求指向數據庫層。
解決方案:
這種場景可以從代碼邏輯層面優化,從緩存中查詢不到數據,再次將請求轉向數據庫中的時候,鎖定該key,獲取到該key之后,將該key寫入緩存,偽代碼如下

value = get_value_from_redis(key1)
if not value:
    if exclusiveness_lock(key1):#成功排他性鎖定目標,請求指向數據庫
        value = get_value_from_mysql(key1)
      if value:
          write_key_to_redis(key1,value)
    else:#無法獲取排他性鎖,間隔0.1s之后再次查詢緩存
        time.sleep(0.1)
        # 再次從緩存中查詢
        get_value_from_redis(key1)       

緩存雪崩
某些原因,比如:
1,Redis實例(主從,集群,哨兵等等)故障。
2,Redis中的key由於過期時間已到,自動過期。
3,由於Redis內存策略導致(maxmemory,maxmemory-policy配置)某些key失效(過期,被清理出緩存等)。
如果此時出現高並發的請求出現,這些請求會全部指向數據庫層,緩存層失去了對數據庫層的保護,導致數據庫承擔絕大壓力的情況。
解決方案:
1,Redis層的高可用,保證緩存層可以有效地保護數據庫層
2,從Redis配置(內存管理策略maxmemory,maxmemory-policy)以及結合業務,避免某些潛在的熱點key值過期
3,應用程序端限流,或者通過隊列的方式等削峰的方式來保護后端數據庫

 


免責聲明!

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



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