Java實現緩存和redis緩存穿透和緩存雪崩的一些研討

Java緩存的一些使用和體會

公司用到的本地緩存

https://github.com/PhantomThief/zknotify-cache
一直以爲用的公司提供的本地緩存是封裝的別的緩存模塊。結果找到GitHub上一看,這個本地緩存是公司大佬寫得一個。瞬間佩服之至,先把源碼下下來,回頭把這個源碼分析一波。

Redis的緩存

一般情況下,針對大型的使用場景,我目前用的最多的緩存方案就兩種,第一種是上面提到的本地緩存。第二種就是Redis,Redis就不用說了,非常優秀。針對數據庫緩存的話Redis主要的實現方法是,先查Redis,如果有則返回,沒有則到數據庫裏面去查找。有的話返回並且寫入到Redis。具體流程:在這裏插入圖片描述

redis緩存穿透

爲什麼會出現

正常情況下,我們去查詢數據都是存在。

那麼請求去查詢一條壓根兒數據庫中根本就不存在的數據,也就是緩存和數據庫都查詢不到這條數據,但是請求每次都會打到數據庫上面去。

這種查詢不存在數據的現象我們稱爲緩存穿透。

後果

如果產生大量的緩存穿透現象,會給數據庫造成大量的壓力,加不加緩存都沒用了。

怎麼辦

1. 緩存空值

之所以會發生穿透,就是因爲緩存中沒有存儲這些空數據的key。從而導致每次查詢都到數據庫去了。那麼我們就可以爲這些key對應的值設置爲null 丟到緩存裏面去。後面再出現查詢這個key 的請求的時候,直接返回null 。這樣,就不用在到數據庫中去走一圈了,但是別忘了設置過期時間。

2. BloomFilter

緩存擊穿

在平常高併發的系統中,大量的請求同時查詢一個 key 時,此時這個key正好失效了,就會導致大量的請求都打到數據庫上面去。這種現象我們稱爲緩存擊穿。會造成某一時刻數據庫請求量過大,壓力劇增。

解決方案

上面的現象是多個線程同時去查詢數據庫的這條數據,那麼我們可以在第一個查詢數據的請求上使用一個 互斥鎖來鎖住它。

其他的線程走到這一步拿不到鎖就等着,等第一個線程查詢到了數據,然後做緩存。後面的線程進來發現已經有緩存了,就直接走緩存。

緩存雪崩

緩存雪崩的情況是說,當某一時刻發生大規模的緩存失效的情況,比如你的緩存服務宕機了,會有大量的請求進來直接打到DB上面。結果就是DB 稱不住,掛掉。

解決熱點數據集中失效問題

我們在設置緩存的時候,一般會給緩存設置一個失效時間,過了這個時間,緩存就失效了。

對於一些熱點的數據來說,當緩存失效以後會存在大量的請求過來,然後打到數據庫去,從而可能導致數據庫崩潰的情況。

爲了避免這些熱點的數據集中失效,那麼我們在設置緩存過期時間的時候,我們讓他們失效的時間錯開。比如在一個基礎的時間上加上或者減去一個範圍內的隨機值。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章