摘要:當緩存空間滿了,同步失敗,網絡阻塞,緩存寫失敗等原因,會出現緩存服務器上并沒有這個。這種問題,以前有過實踐,修改數據庫成功,而修改緩存失敗的情況,最主要就是緩存服務器掛了。而緩存服務器掛了,請求首先自然也就無法到達,從而直接訪問到數據庫。
原文摘自:
緩存穿透、并發和失效,來自一線架構師的解決方案
https://community.qingcloud.com/topic/463
在我們的實踐中,原文中有部分解決方案已經過時,在原文的基礎上,添加了幾個我們常用的方案。
http://www.4wei.cn/archives/1002621
我們在用緩存的時候,不管是Redis或者Memcached,基本上會通用遇到以下三個問題:
緩存穿透
緩存并發
緩存失效
同步、復制中斷
緩存穿透注:上面三個圖會有什么問題呢?
我們在項目中使用緩存通常都是先檢查緩存中是否存在,如果存在直接返回緩存內容,如果不存在就直接查詢數據庫然后再緩存查詢結果返回。
這個時候如果我們查詢的某一個數據在緩存中一直不存在,就會造成每一次請求都查詢DB,這樣緩存就失去了意義,在流量大時,可能DB就掛掉了。
那這種問題有什么好辦法解決呢?
要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。有一個比較巧妙的作法是,可以將這個不存在的key預先設定一個值。比如,"key" , “&&”。
在返回這個&&值的時候,我們的應用就可以認為這是不存在的key,那我們的應用就可以決定是否繼續等待繼續訪問,還是放棄掉這次操作。如果繼續等待訪問,過一個時間輪詢點后,再次請求這個key,如果取到的值不再是&&,則可以認為這時候key有值了,從而避免了透傳到數據庫,從而把大量的類似請求擋在了緩存之中。
你應該注意,這里緩存未命中的原因,更值得我們關注。
當緩存空間滿了,同步失敗,網絡阻塞,緩存寫失敗等原因,會出現緩存服務器上并沒有這個key。
或者因為同步中斷,在主從架構中,寫到主卻未同步到從的悲劇,就會出現請求穿透到DB層的情況。
出現這樣的情況,一定不能直接將請求穿透到DB層,避免DB當機影響其它業務。
我們的解決方案可以參考。
當業務中請求量特別高,緩存未命中的情況,應該在建立DB保護的基礎上,放棄一定比例的請求,直接返回空
可以隨機釋放一些請求到DB,控制好流量的話,能保證緩存重建且DB不受極端壓力
后端異步定時檢查緩存,主動建立這些緩存
部分頁面可緩存永不過期,后端異步定時檢查緩存,主動更新、重建緩存,后端失效也可實現業務降級
通過建立二級緩存,把之前成功獲取的緩存數據放到本機緩存,文件也好,共享內存也好,接受一些過期數據
緩存并發有時候如果網站并發訪問高,一個緩存如果失效,可能出現多個進程同時查詢DB,同時設置緩存的情況,如果并發確實很大,這也可能造成DB壓力過大,還有緩存頻繁更新的問題。
我現在的想法是對緩存查詢加鎖,如果KEY不存在,就加鎖,然后查DB入緩存,然后解鎖;其他進程如果發現有鎖就等待,然后等解鎖后返回數據或者進入DB查詢。
這種情況和剛才說的預先設定值問題有些類似,只不過利用鎖的方式,會造成部分請求等待。
緩存失效引起這個問題的主要原因還是高并發的時候,平時我們設定一個緩存的過期時間時,可能有一些會設置1分鐘啊,5分鐘這些,并發很高時可能會出在某一個時間同時生成了很多的緩存,并且過期時間都一樣,這個時候就可能引發一當過期時間到后,這些緩存同時失效,請求全部轉發到DB,DB可能會壓力過重。
那如何解決這些問題呢?
其中的一個簡單方案就時講緩存失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件。
我們討論的第二個問題時針對同一個緩存,第三個問題時針對很多緩存。
接下來我們將發表一些自己的緩存高可用實踐,如《基于云平臺的緩存集群高可用實踐》,歡迎關注。
總結
1、緩存穿透:查詢一個必然不存在的數據。比如文章表,查詢一個不存在的id,每次都會訪問DB,如果有人惡意破壞,很可能直接對DB造成影響。
2、緩存失效:如果緩存集中在一段時間內失效,DB的壓力凸顯。這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布。
當發生大量的緩存穿透,例如對某個失效的緩存的大并發訪問就造成了緩存雪崩。
精彩問答
問題:如何解決DB和緩存一致性問題?
當修改了數據庫后,有沒有及時修改緩存。這種問題,以前有過實踐,修改數據庫成功,而修改緩存失敗的情況,最主要就是緩存服務器掛了。而因為網絡問題引起的沒有及時更新,可以通過重試機制來解決。而緩存服務器掛了,請求首先自然也就無法到達,從而直接訪問到數據庫。那么我們在修改數據庫后,無法修改緩存,這時候可以將這條數據放到數據庫中,同時啟動一個異步任務定時去檢測緩存服務器是否連接成功,一旦連接成功則從數據庫中按順序取出修改數據,依次進行緩存最新值的修改。
問題:問下緩存穿透那塊!例如,一個用戶查詢文章,通過ID查詢,按照之前說的,是將緩存的KEY預先設置一個值,,如果通過ID插過來,發現是預先設定的一個值,比如說是“&&”,那之后的繼續等待訪問是什么意思,這個ID什么時候會真正被附上用戶所需要的值呢?
我剛說的主要是咱們常用的后面配置,前臺獲取的場景。前臺無法獲取相應的key,則等待,或者放棄。當在后臺配置界面上配置了相關key和value之后,那么以前的key &&也自然會被替換掉。你說的那種情況,自然也應該會有一個進程會在某一個時刻,在緩存中設置這個ID,再有新的請求到達的時候,就會獲取到最新的ID和value。
問題:其實用Redis的話,那天看到一個不錯的例子,雙key,有一個當時生成的一個附屬key來標識數據修改到期時間,然后快到的時候去重新加載數據,如果覺得key多可以把結束時間放到主key中,附屬key起到鎖的功能。
這種方案,之前我們實踐過。這種方案會產生雙份數據,而且需要同時控制附屬key與key之間的關系,操作上有一定復雜度。
問題:多級緩存是什么概念呢?
多級緩存就像我今天之前給大家發的文章里面提到了,將Ehcache與Redis做二級緩存,就像我之前寫的文章 http://www.jianshu.com/p/2cd6ad416a5a 提到過的。但同樣會存在一致性問題,如果我們需要強一致性的話,緩存與數據庫同步是會存在時間差的,所以我們在具體開發的過程中,一定要根據場景來具體分析,二級緩存更多的解決是,緩存穿透與程序的健壯性,當集中式緩存出現問題的時候,我們的應用能夠繼續運行。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/61707.html
摘要:當緩存空間滿了,同步失敗,網絡阻塞,緩存寫失敗等原因,會出現緩存服務器上并沒有這個。這種問題,以前有過實踐,修改數據庫成功,而修改緩存失敗的情況,最主要就是緩存服務器掛了。而緩存服務器掛了,請求首先自然也就無法到達,從而直接訪問到數據庫。 原文摘自: 緩存穿透、并發和失效,來自一線架構師的解決方案https://community.qingcloud.com/topic/463 在我們...
摘要:當緩存空間滿了,同步失敗,網絡阻塞,緩存寫失敗等原因,會出現緩存服務器上并沒有這個。這種問題,以前有過實踐,修改數據庫成功,而修改緩存失敗的情況,最主要就是緩存服務器掛了。而緩存服務器掛了,請求首先自然也就無法到達,從而直接訪問到數據庫。 原文摘自: 緩存穿透、并發和失效,來自一線架構師的解決方案https://community.qingcloud.com/topic/463 在我們...
摘要:方案二布隆過濾器攔截布隆過濾器介紹概念布隆過濾器英語是年由布隆提出的。這就是布隆過濾器的基本思想。防緩存穿透的布隆過濾器判斷是否為合法非法則不允許繼續查庫從緩存中獲取數據緩存為空從數據庫中獲取緩存空對象參考書籍開發與運維 上周在工作中遇到了一個問題場景,即查詢商品的配件信息時(商品:配件為1:N的關系),如若商品并未配置配件信息,則查數據庫為空,且不會加入緩存,這就會導致,下次在查詢同...
閱讀 1897·2021-11-24 09:39
閱讀 2134·2021-09-22 15:50
閱讀 1991·2021-09-22 14:57
閱讀 699·2021-07-28 00:13
閱讀 1064·2019-08-30 15:54
閱讀 2356·2019-08-30 15:52
閱讀 2686·2019-08-30 13:07
閱讀 3787·2019-08-30 11:27