redis應用實戰(快取一致性,快取雪崩)
對於讀多寫少的高併發場景,我們會經常使用快取來進行優化。比如說支付的餘額展示功能,實際上99%的時候
都是查詢,1%的請求是變更(除非是土豪,每秒鐘都有收入在不斷更改餘額),所以,我們在這樣的場景下,可
以加入快取,使用者->餘額
Redis快取與資料一致性問題
那麼基於上面的這個出發點,問題就來了,當用戶的餘額發生變化時,如何更新快取中的資料?
1.我們是先更新快取中的資料再更新資料庫的資料
2.還是修改資料庫的資料,再更新快取中的資料
這就是我們經常會在面試遇到的問題,資料庫的資料和快取中的資料如何達到一致性?首先,可以肯定的是,
redis中的資料和資料庫中的資料不可能保證事務性達到統一的,這個是毫無疑問的,所以在實際應用中,我們都
是基於當前的場景進行權衡降低出現不一致問題的出現概率
更新快取還是讓快取失效
更新快取表示資料不但會寫入到資料庫,還會同步更新快取; 而讓快取失效是表示只更新資料庫中的資料,然後刪
除快取中對應的key。那麼這兩種方式怎麼去選擇?這塊有一個衡量的指標。
1.如果更新快取代價很小,那麼可以先更新快取,這個代價很小的意思是我不需要很複雜的計算去獲得最新的餘額數字等。
2.如果是更新快取的代價很大,意味著需要通過多個介面呼叫和資料查詢才能獲得最新的結果,那麼可以先淘汰
快取。淘汰快取以後後續的請求如果在快取中找不到,自然去資料庫中檢索。
先操作資料庫還是先操作快取?
當客戶端發起事務型別請求時,假設我們以讓快取失效作為快取的的處理方式,那麼又會存在兩個情況,
1.先更新資料庫在讓快取失效
2.先讓快取失效,在更新資料庫
更新資料庫和更新快取這兩個操作,是無法保證原子性的,所以我們需要根據當前業務場景的容忍性來選擇,也就是如果出現不一致的情況下,哪一種更新方式對業務的影響最小,就先執行影響最小的方案。
最終一致性的解決方案
關於快取雪崩的解決方案
當快取大規模滲透在整個架構中以後,那麼快取本身的可用性將決定整個架構的穩定性。那麼接下來我們來討論下
快取在應用過程中可能會導致的問題。
快取雪崩
快取穿透是指查詢一個根本不存在的資料,快取和資料來源都不會命中,出於容錯考慮,如果從資料層查不到資料則不寫入快取,即資料來源返回值為null時,不存在null,快取穿透問題可能會使後端資料來源負載加大,由於很多後端資料來源不具備高併發性,甚至可能造成後端資料來源宕掉
解決方式
1.如果查詢資料庫也為空,直接設定一個預設值存放到快取,這樣第二次到緩衝中獲取就有值了,而不會繼續訪
問資料庫,這種辦法最簡單粗暴。比如,”key” , “&&”。
再返回這個&&值的時候,我們的應用就可以認為這是不存在的key,那我們的應用就可以決定是否繼續等待繼續訪問,還是放棄掉這次操作。如果繼續等待訪問,過一個時間輪訓點後,再次請求這個key,如果取到的值不再是&&,則可以認為這時候key有值了,從而避免了透傳到資料庫,從而把大量的類似請求擋在了快取之中。
2.根據快取資料Key的設計規則,將不符合規則的key進行過濾
採用布隆過濾器,將所有可能存在的資料雜湊到一個足夠大的BitSet中,不存在的資料將會被攔截掉,從而避免了
對底層儲存系統的查詢壓力
下面一篇文章會講到布隆過濾器