快取用不好,Bug改到老

前言

日常工作中,快取的使用隨處可見。快取使用得當,對提升系統的效能,提高使用者體驗感有著至關重要的作用。但是如果使用不當,就會出現一些令人費解或者資料混亂的問題。本文將給大家普及常見的一些快取使用與快取使用過程中的踩坑點,希望能幫助大家更好的理解與使用快取,文中如有寫的不對的地方,歡迎大家留言指正。

java快取形式/介質

眾所周知,快取之所以訪問速度快,是因為把快取的互動介質是記憶體。而常規的例如mysql資料互動介質是磁碟。那麼常見的java中或者中介軟體供我們可以用來做快取的開發的工具有幾種呢?

jvm本地記憶體

jvm本地記憶體常見使用為定義一個全域性靜態變數,保證後端服務在執行過程中,對應的物件空間直接保持被引用,不會被GC給回收。

guava快取工具類

儲存資料的本質與jvm記憶體類似,內部依靠維護java集合的子類來儲存資料,但是提供了快取資料的過期時間,過期策略等設定,像一個小型的中介軟體。

redis

Redis 是完全開源的,遵守 BSD 協議,是一個高效能的 key-value 資料庫。常用作資料庫、快取和訊息代理。Redis 提供了諸如字串、雜湊、列表、集合、帶範圍查詢的排序集合、點陣圖、hyperloglogs、地理空間索引和流streams等資料結構。Redis 內建複製、支援 Lua 指令碼、支援 LRU 快取淘汰策略、事務和不同級別的磁碟持久化,並透過 Redis Sentinel 和 Redis Cluster 自動分割槽提供高可用性。同類型中介軟體中,Redis是最火的,沒有之一。

幾種常用快取的對比

快取常見的坑

在分析快取的坑之前我們先來看一下快取的增刪改查如何保證資料庫與快取的資料一致性。

查詢

image-20210529105335719。png

查詢時先查詢快取,如果快取存在直接返回,不存在則查詢資料庫,將資料庫查詢結果寫入快取【此處預設資料庫存在資料,不存在的情況後面分析】,然後將快取的結果資料返回。

增刪改

image-20210529105531020。png

增刪改時先增刪改資料庫,保證資料庫資料先被修改,然後同步快取內資料,如果中間發生異常,則呼叫資料庫事務回滾資料。

快取穿透

概念

正常情況下,查詢的資料都存在,如果請求一個不存在的資料,也就是快取和資料庫都查不到這個資料,每次都會去資料庫查詢,這種查詢不存在資料的現象我們稱為快取穿透。如上圖,使用者一直請求介面查詢不存在的id資料【資料庫中只存在id>0的資料】,對應的資料永遠不可能在快取中。在高併發場景下,大量請求打到了資料庫,資料庫可能被突發的流量給打掛。

3。1。2。解決方式

1.過濾垃圾資料

在知道查詢的id資料大於0或者基於id是某種規則【例如雪花id】生成的情況下。過濾掉資料庫中不可能的存在的請求。方法入口直接增加一個引數校驗。

2.快取空值

發生穿透的原因是資料在資料庫中不存在,那我們把null值給快取下來,當請求到達時直接返回null。當然這裡對快取是必須加上過期時間的,以免後續真的存在此id的資料。過期時間不宜過長,根據實際業務場景併發量來進行設定。

3.IP攔截

對於惡意的攻擊請求,一直請求無效的資料,可以設定ip請求策略。如果對應的ip短時間內發起了大量請求,且請求引數均為不存在的資料。則將ip進行封禁一段時間,不允許再次請求系統。

**4。布隆過濾器

布隆過濾器(BloomFilter)用來判斷某個元素(key)是否存在於某個集合中我們把有資料的key都放到BloomFilter中,每次查詢的時候都先去BloomFilter判斷,如果沒有就直接返回null 。

注意BloomFilter沒有刪除操作

,對於刪除的key,查詢就會經過BloomFilter然後查詢快取再查詢資料庫,所以BloomFilter可以結合快取空值用,對於刪除的key,可以在快取中快取

快取擊穿

嚴格意義上說快取穿透是快取擊穿的一種。只不過快取擊穿是查詢的有效資料。在高併發情況下,查詢快取時,快取中的資料不存在或者已經失效了。那麼會導致大量的請求打到了資料庫,打掛資料庫

解決方式

先來分析一下場景,大量請求同時到了快取,快取不存在,再請求資料庫。然後再將請求結果寫入到快取。問題就是多個執行緒幾乎同時讀取快取,又幾乎同時重寫快取。多執行緒併發下解決問題,當然是用鎖。單體應用可以使用synchronized關鍵字或者ReentrantLock進行加鎖,分散式服務則可使用分散式鎖的方式來實現加鎖。

大致的虛擬碼如下:

快取雪崩

概念

快取雪崩也是快取擊穿的一種,快取設定了過期時間/淘汰策略的情況下,在某個時間點,大量的快取失效。高併發情況下大量請求打到了資料庫。

解決方式

快取雪崩時,請求方式與快取擊穿一致,主要如何防護快取雪崩,基本指導思想為:

熱點資料設定永不過期,快取淘汰策略為淘汰最早過期資料

資料快取過期時間設定高離散度隨機值,避免某個時間點,大量快取同時過期。

效能問題

概念

使用了快取,但是效能還是上不去的場景。例如雙十一場景下,訂單資料量比較大。如果新增修改刪除所有操作都要先操作一遍資料庫,再回寫快取的話效率是很低的。

解決方式

把快取當做資料庫來使用,當然這裡需要使用redis這種高可用的持久化快取中介軟體。資料存在redis中,資料互動都直接互動redis。扛過流量高峰之後,啟用定時任務,將redis的資料刷入至資料庫或者ES。當然這裡也可以使用訊息佇列,這裡不具體展開。

總結

本文著重講述了快取的增刪改查策略與日常坑點。

資料一致性

查詢操作,先走快取再走資料庫,再更新快取。

增刪改操作,先走資料庫再更新快取。

坑點

從快取雪崩去理解快取穿透與快取擊穿。

高效能

讀寫持久化快取資料,非同步刷盤mysql。

重磅訊息:Spring 6 和Spring Boot 3

2021-09-03

一個SpringMVC介面能返回JSON又能返回XML? 安排!

2021-08-31

TAG: 快取資料庫資料查詢請求