Redis快取解決方案

2021-09-26 14:33:57 字數 2323 閱讀 4129

使用快取業務流程大概:查詢時,先查快取——有,直接返回;無,查資料庫返回。

接下來說一下快取在實際應用中可能出現的問題:

快取穿透:由於快取是不命中時被動寫入的,出於容錯考慮,當查詢乙個一定不存在的資料時——儲存層查不到資料不寫入快取——導致每次查詢這個不存在的資料請求都會直接到儲存層查詢,失去了快取的意義。

如果黑客對你的系統進行攻擊,拿乙個不存在的id去查詢資料,產生大量的請求到你的資料庫,可能會導致你的資料庫由於壓力過大而宕掉。

之所以會發生穿透,是因為快取中沒有儲存這些空資料的key。從而導致每次查詢都到資料庫去了。

可將這些key設定為null丟到快取裡邊,當出現查詢這個key的請求時,返回null。這樣做每次查詢無需再走資料庫,但是別忘了設定過期時間。

快取空值帶來的問題:

第一,空值做了快取,意味著快取層中存了更多的鍵,需要更多的記憶體空間 ( 如果是攻擊,問題更嚴重 ),比較有效的方法是針對這類資料設定乙個較短的過期時間,讓其自動剔除。

第二,快取層和儲存層的資料會有一段時間視窗的不一致,可能會對業務有一定影響。例如過期時間設定為 5分鐘,如果此時儲存層新增了這個資料,那此段時間就會出現快取層和儲存層資料的不一致,此時可以利用訊息系統或者其他方式清除掉快取層中的空物件。

bloomfilter類似於乙個hbase set用來判斷某個元素(key)是否存在於某個結合中。

這種方式在大資料場景應用比較多,比如hbase中使用它去判斷資料是否在磁碟上。還有在爬蟲場景判斷url是否已經被爬取過。

這種方案可以加在第一種方案中,在快取之前加一層bloomfilter:

先去bloomfilter去查詢key是否存在——如果不存在就直接返回,存在再去查快取——查資料庫

針對於一些惡意攻擊,攻擊帶來大量key是不存在的,那麼我們採用第一種方案就會快取大量不存在的資料。此時我們採用第一種方案就不合適了,我們完全可以先使用第二種方案過濾掉這些key。

針對這些key異常多,請求多,重複率比較低的資料,我們就沒有必要進行快取,使用第二種方案直接過濾掉。

而對於空資料的key有限的,重複率比較高的,我們則可以採用第一種方式進行快取。

快取擊穿:在平時高併發的系統中,大量的請求同時查詢乙個key時,這個key正好失效,就會導致大量的請求都打到資料庫上面去的現象。

會造成某一時刻資料請求量過大,壓力劇增。

上面現象是多個執行緒同時去查詢資料庫的這一條資料,那麼我們可以在第乙個查詢資料的請求上使用乙個互斥鎖來鎖住它。(如果是單機,可以用synchronized或者lock來處理,如果是分布式環境可以用分布式鎖就可以了(分布式鎖,可以用memcache的add, redis的setnx, zookeeper的新增節點操作))

setnx key value
將 key 的值設為 value,當且僅當 key 不存在。 

若給定的 key 已經存在,則 setnx 不做任何動作。 

setnx 是set if not exists的簡寫。

其他執行緒走到這一步拿不到鎖就等著,等待第乙個執行緒查詢到了資料,然後做快取。後面的執行緒進來發現已經有了快取,就直接走快取。

快取雪崩的情況是指:當某一時刻發生大規模的快取失效的情況,比如你的快取服務宕機了,會有大量的請求進來直接打到資料庫上面,結果就是資料庫掛掉。

這種方案就是在發生雪崩前對快取集群,實現高可用,如果是使用redis,可以使用(主從  +  哨兵),redis cluster來避免redis全盤崩潰的情況。

使用ehcache本地快取的目的也是考慮redis cluster完全不可用的時候,ehcache本地快取還能夠支撐一陣。

使用hystrix進行限流 & 降級,比如一秒來了5000個請求,我們可以設定假設一秒只能有2000個請求可以通過這個元件,那麼其他剩餘的3000請求就會走限流邏輯。

然後去呼叫我們自己開發的降級元件(降級),比如設定的一些預設值等等之類的。以此來保護最後的mysql不會被大量的請求打死。

一旦重啟,就能從磁碟上自動載入資料恢復記憶體中的資料。

我們在設定快取的時候,一般會給快取設定乙個失效的時間,過了這個時間,快取就失效了。

對於一些熱點資料來說,當快取失效後會存在大量的請求到資料庫上來,從而可能導致資料庫崩潰的情況。

為了避免這些熱點資料集體失效,那麼我們在設定快取過期時間的時侯,讓他們失效的時間錯開。比如我們可以在原有的失效時間基礎上增加乙個隨機值。

結合上面的擊穿情況,在第乙個請求去查詢資料庫的時候對它加乙個互斥鎖,其餘的查詢請求都會被阻塞住,直到鎖被釋放,從而保護資料庫。

但是也是由於它會阻塞其他執行緒,此時系統的吞吐量會下降。需要結合實際業務去考慮。

Redis 快取雪崩和快取穿透 解決方案

造成的原因 1.業務自身 或資料出現問題 2.一些惡意攻擊 爬蟲造成大量空的命中,此時會對資料庫造成很大壓力。解決方法 1.設定布隆過濾器,將所有可能存在的資料雜湊到乙個足夠大的bitmap中,乙個一定不存在的資料會被這個bitmap攔截掉,從避免了對底層儲存系統的查詢壓力。2.如果乙個查詢返回的資...

Redis 快取穿透問題及解決方案

快取穿透問題 快取穿透是指查詢乙個根本不存在的資料,快取層和儲存層都不會命中,通常出 於容錯的考慮,如果從儲存層查不到資料則不寫入快取層。一般對於未命中的資料我們是按照如下方式進行處理的 1.快取層不命中。2.儲存層不命中,不將空結果寫回快取。3.返回空結果。快取穿透問題 在資料庫中未查找到資料,未...

Redis 快取穿透 快取雪崩原理及解決方案

redis快取的場景 客戶端請求在快取層命中就直接返回,如果miss就去讀取儲存層,儲存層讀取到就寫入快取層,然後再返回到客戶端 redis的優缺點 快取穿透 引發原因 在查詢乙個一定不存在的資料,由於快取是不命中時被動寫入,並且處於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的...