搜尋
首頁資料庫Redis分析Redis中熱點key儲存問題,聊聊快取異常的解決方法

這篇文章帶大家聊聊Redis中的三種常見快取異常:快取穿透、快取擊穿和快取雪崩,透過它們來聊一聊Redis中的熱點key儲存問題,希望對大家有幫助!

分析Redis中熱點key儲存問題,聊聊快取異常的解決方法

相關推薦:《一起分析Redis快取一致性、快取穿透、快取擊穿及快取雪崩問題

快取穿透、快取擊穿和快取雪崩是Redis面試當中和實際開發中,經常需要考慮的問題。很多人對該問題的產生、原因和解決方案還是不夠清晰。其實大家針對該三種情況,去仔細分析一個產生的原理就能很好的找到一個好的解決方案。 【相關推薦:Redis影片教學

本文透過定義、案例、危害和解決方案的幾個角度,來幫助你快速了解該三個問題。

相信大家在網路上也看到很多解決這三種問題的解決方案,其中的一些方案是否是一個正確的方案呢?本文也將一一分析此類方案的優缺點。

下圖為本文的內容大綱,文章也是圍繞這幾點進行分析與總結。

分析Redis中熱點key儲存問題,聊聊快取異常的解決方法

三個比較

  • #快取穿透、快取擊穿和快取雪崩都是因為快取中資料不存在,導致走資料庫去查詢資料。

  • 由於快取資料不存在,所有的請求都會走到資料庫,因此會導致資料庫的壓力過大甚至出現服務崩潰,導致整個系統無法使用。

快取穿透

#定義:快取穿透是由於客戶端求的資料在快取中不存在,然後去查詢資料庫,然而資料庫沒有客戶端要查詢的數據,導致每一次請求都會走資料庫查詢操作。 真正的問題在於該資料本身就是不存在的

範例:客戶端要求商品詳情資訊時,攜帶一個商品ID,此時該商品ID是不存在的(不管是快取中還是資料庫中)。導致每一次要求該ID商品的資料資訊都會走資料庫。

危害:由於請求的參數對應的資料根本不存在,會導致每一次都會請求資料庫,增加資料庫的壓力或服務崩潰,更有甚至影響到其他的業務模組。經常發生在使用者惡意請求的情況下會發生。

解決方案:

1、根據請求的參數快取一個null值。並且為該值設定一個過期時間,可以將時間設定短暫一點。

2、使用布隆過濾器,先透過布隆過濾器進行篩選,如果在過濾器中存在則去查詢資料庫,然後再加入到快取中。如果不存在則直接傳回客戶端資料不存在。

3、由於快取穿透可能是使用者發起惡意請求,可以將使用者ip給記錄下來,針對惡意的ip請求進行封鎖。

方案分析:

  • 第一個方案,針對不存在的key,會快取一個空的值。假設這樣的請求特別多,是否都會一一去設定一個空值的緩存,此時Redis中就存在大量無效的緩存空值。假設這樣的key是商品或文章類別的ID,我們在設定空值之後,如果後台加入資料應該去更新ID對應的快取值,並設定一個合理的過期時間。

  • 第二種方案,也是業界使用最多的方案。布隆過濾器的優點在於基於Redis實現,記憶體操作且底層的實作也是非常節約記憶體。當後台新增資料成功時,將該資料的ID加入到布隆過濾器中,前端在請求時先走布隆過濾器進行驗證是否存在。但布隆過濾器也存在一個弊端,就是hash衝突問題。這裡的hash衝突是什麼意思呢?是說多個ID在進行hash計算時,得到的hash位元都是同一個值,這就導致在驗證是否存在時誤判。本身是有的,得到的結果是沒有。 布隆過濾器的一個弊端就是,它說有不一定有,它說沒有就一點是沒有的。

  • 第三種方案,針對同一用戶一段時間內發起大量的請求,觸發快取穿透機制,此時我們可以顯示該客戶端的存取。但攻擊者如果是發動DDOS這樣的攻擊,是沒辦法完全的避免此類攻擊,因此這種方案不是一個很好的解決方案。

方案總結:

#
  • 我們先在請求層級增加第3中方案,做一個限流機制、IP黑名單機制,控制一些惡意的請求,如果是誤判我們可以實現IP解封這樣的操作。在快取層則使用第1中方案實作。設定一個合理的快取時間。

  • 對於能容忍誤判的業務場景,可以直接才用第2方案實現。完全基於Redis,減少了系統的複雜度。

快取擊穿

#定義:快取擊穿是因為某個熱點key不存在,導致走資料庫查詢。增加了資料庫的壓力。這種壓力可能是瞬間的,也可能是比較持久的。 真正的問題在於該key是存在,只是快取中不存在,導致走資料庫操作

範例:有一個熱門的商品,用戶查看商品詳情時攜帶商品的ID以獲取到商品的詳情資訊。此時快取中的資料已經過期了,因此來的所有請求都要走資料庫去查詢。

危害:相對快取穿透而言,該資料在資料庫中是存在的,只是因為快取過期了,導致要走一次資料庫,然後在加入到快取中,下次請求就能正常走快取.所謂的危害同樣的還是針對資料庫層面的危害。

解決方案:

1、加互斥鎖。針對第一個請求,發現快取中沒有數據,此時查詢資料庫加入到快取裡面。這樣後面的請求就不需要走資料庫查詢。

2、增加業務邏輯過期時間。在設定快取時,我們可以新增一個快取過期時間。每次去讀取的時候,做一個判斷,如果這個過期時間與當前時間小於一個範圍,觸發一個後台線程,去數據庫拉取一下數據,接著更新一下緩存數據和緩存的過期時間。其實原理就是程式碼層面給快取延長快取時長。

3、資料預熱。實作透過後台把資料加到快取裡面。例如秒殺場景開始前,就把商品的庫存加到快取裡面,這樣使用者請求來了之後,就直接走快取。

4、永久不過期。在給快取設定過期時間時,讓它永久不過期。後台單獨開啟一個線程,來維護這些快取的過期時間和資料更新。

方案分析:

  • 互斥鎖保證了只有一個請求走資料庫,這是一個優點。但是對於分散式的系統,得才用分散式鎖實現,分散式鎖的實作本身就有一定的困難,這樣提升了系統的複雜度。

  • 第2種方案,利用Redis不過期,業務過期的方案實現。保證了每一次請求都能拿到數據,同時也可以做到一個後台執行緒去更新數據。缺點在於後台執行緒沒有更新完數據,此時請求拿到的數據是舊數據,可能對應即時性要求高的業務場景有弊端。

  • 第3種方案,使用快取預熱每次載入都走緩存,與第2種方案差不多。不過也存在熱點資料更新問題,因此此方案適合資料即時性要求不高的資料。

  • 第4中方案,和第2、3種方案類似,在此基礎上進行了一定優化,使用後台非同步執行緒主動去更新快取資料。難點在於更新的頻率控制。

方案總結:

  • #對於即時性要求高的數據,推薦使用第1種方案,雖然在技術上有一定的難度但是能做到數據的即時性處理。如果發生某些請求等待時間久,可以傳回異常,讓客戶端重新發送一次請求。

  • 對於即時性要求不高的數據,可以使用第4種方案。

快取雪崩

# 定義:前面說到快取擊穿,是因為快取中的某個熱點key失效,導致大量請求走資料庫。然而緩存雪崩其實也是同樣的道理,只不過這個更嚴重而已,是大部分緩存的key失效,而不是一個或者兩個key失效。

範例:在一個電商系統中,某一個分類下的商品資料在快取中都失效了。然而當前系統的許多請求都是該分類下面的商品資料。這樣就導致所有的請求都走資料庫查詢。

危害:由於一瞬間大量的請求湧入,每個請求都要走資料庫進行查詢。資料庫瞬間流量湧入,嚴重增加資料庫負擔,容易導致資料庫直接癱瘓。

解決方案:

1、快取時間隨機。因為某一時間,大量的快取失效,說明快取的過期時間比較集中。我們直接將過期的時間設定為不集中,隨機打亂。這樣快取過期時間相對不會很集中,就不會出現同一時刻大量請求走資料庫進行查詢操作。

2、多層快取。不單純的靠Redis來做緩存,我們也可以使用memcached來做緩存(這裡只是舉一個例子,其他的快取服務也可以)。快取資料時,對Redis做一個緩存,對memcached做一個快取。如果Redis失效了,我們可以走memcached。

3、互斥鎖。快取擊穿中我們提到了使用互斥鎖來實現,同樣我們也可以用在雪崩的情況下。

4、設定過期標誌。其實也可以用到快取擊穿中講到的永久不過期。當請求時,判斷過期時間,如果臨近過期時間則設定過期標誌,觸發一個獨立的執行緒去對這個快取進行更新。

方案分析:

  • 第1種方案採用隨機數快取時間,能確保key的失效時間分散。困難在於如何設定快取時間,如果對於一些需要設定短快取時間並且資料量非常大的數據,則該方案就需要合理的控制時間。

  • 第2種方案使用多層緩存,可以保證請求全部走緩存資料。但這樣增加了系統的架構難度,以及其他的各種問題,例如快取多層次更新。

  • 第3種方案使用互斥鎖,在快取擊穿中我們提到了互斥鎖,在雪崩的場景中我們雖然能使用,但是這樣會產生大量的分佈式鎖。

  • 第4種方案使用邏輯快取時間,很好的保證了系統的快取壓力。

方案總結:

在實際的專案中推薦使用第1、2和4種方案試下會更好一些。

總結

  • 快取穿透是因為資料庫本身沒有該資料。

  • 快取擊穿和快取雪崩是資料庫中存在該數據,只是快取中的資料失效了,導致重新要查詢一次資料庫再加入到快取中去。

  • 快取擊穿是針對部分熱點key,而快取雪崩是大面積快取失效。兩則原理上其實是一樣的,無非就是針對快取的key的劃分不同而已。    

更多程式設計相關知識,請造訪:程式設計入門! !

以上是分析Redis中熱點key儲存問題,聊聊快取異常的解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:learnku。如有侵權,請聯絡admin@php.cn刪除
es和redis区别es和redis区别Jul 06, 2019 pm 01:45 PM

Redis是现在最热门的key-value数据库,Redis的最大特点是key-value存储所带来的简单和高性能;相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,ES的特点是搜索,ES是围绕搜索设计的。

一起来聊聊Redis有什么优势和特点一起来聊聊Redis有什么优势和特点May 16, 2022 pm 06:04 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于redis的一些优势和特点,Redis 是一个开源的使用ANSI C语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式存储数据库,下面一起来看一下,希望对大家有帮助。

Redis实现排行榜及相同积分按时间排序功能的实现Redis实现排行榜及相同积分按时间排序功能的实现Aug 22, 2022 pm 05:51 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,希望对大家有帮助。

实例详解Redis Cluster集群收缩主从节点实例详解Redis Cluster集群收缩主从节点Apr 21, 2022 pm 06:23 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis Cluster集群收缩主从节点的相关问题,包括了Cluster集群收缩概念、将6390主节点从集群中收缩、验证数据迁移过程是否导致数据异常等,希望对大家有帮助。

详细解析Redis中命令的原子性详细解析Redis中命令的原子性Jun 01, 2022 am 11:58 AM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于原子操作中命令原子性的相关问题,包括了处理并发的方案、编程模型、多IO线程以及单命令的相关内容,下面一起看一下,希望对大家有帮助。

一文搞懂redis的bitmap一文搞懂redis的bitmapApr 27, 2022 pm 07:48 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了bitmap问题,Redis 为我们提供了位图这一数据结构,位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已,希望对大家有帮助。

实例详解Redis实现排行榜及相同积分按时间排序功能的实现实例详解Redis实现排行榜及相同积分按时间排序功能的实现Aug 26, 2022 pm 02:09 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,下面一起来看一下,希望对大家有帮助。

一起聊聊Redis实现秒杀的问题一起聊聊Redis实现秒杀的问题May 27, 2022 am 11:40 AM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于实现秒杀的相关内容,包括了秒杀逻辑、存在的链接超时、超卖和库存遗留的问题,下面一起来看一下,希望对大家有帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具