文章目錄
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 稱不住,掛掉。
解決熱點數據集中失效問題
我們在設置緩存的時候,一般會給緩存設置一個失效時間,過了這個時間,緩存就失效了。
對於一些熱點的數據來說,當緩存失效以後會存在大量的請求過來,然後打到數據庫去,從而可能導致數據庫崩潰的情況。
爲了避免這些熱點的數據集中失效,那麼我們在設置緩存過期時間的時候,我們讓他們失效的時間錯開。比如在一個基礎的時間上加上或者減去一個範圍內的隨機值。
結合上面的擊穿的情況,在第一個請求去查詢數據庫的時候對他加一個互斥鎖,其餘的查詢請求都會被阻塞住,直到鎖被釋放,從而保護數據庫。