解決緩存穿透的幾種應用思考


其實在之前的文章【緩存,確實很香,卻也很受傷!】中,對緩存穿透的引發緣由及應對策略做過簡要的描述。這篇文章將對這個問題再做下額外的擴展。

一、關於布隆過濾器

布隆過濾器支持兩種操作:1、添加元素;2、判斷元素是否存在。

布隆過濾器的特性:占用少量內存過濾海量數據

判斷元素存在會返回兩種結果:

1、不存在:表示元素肯定不存在於布隆過濾器中。

2、存在:表示元素可能存在於布隆過濾器中。說可能,是因為這里有個誤差,和布隆過濾器的容量及應用的算法有關。

所以是要判斷存在還是判斷不存在,要結合實際應用中,能否接受誤差,及能夠接受多大的誤差來決定。

二、新聞過濾

你有一個業務爬蟲,不斷的爬取其它新聞網站的文章,然后發布到自己的網站,控制重復文章的發布就變得必不可少,海量的新聞信息,怎么過濾?

基於庫?庫負擔大,效率太低;

基於緩存,存儲已發布的所有新聞到緩存?成本太高,得不償失。

新聞有時效價值,歷史新聞價值極低,顯然基於布隆過濾器的過濾是一個很好的選擇。

三、關系過濾

假如我們有一種業務場景,查詢兩者之間的某種關系數據,比如,a是b是什么關系。

同學?老鄉?生意伙伴?

可能只是同學,或者同學+老鄉,或者同學+老鄉+生意伙伴,又或者什么關系都沒有。

我們有數據庫存儲,也構建了相應的緩存數據來加速響應。

但是當關系數據很少,基數很大時,已有的關系數據相對於所有的窮舉關系就變得很渺小,

這時候,緩存所起到的所用就會變得很小,大部分時間不可避免的會產生穿透,進而進行入庫查詢,那這種問題怎么解決呢?

1、控制查庫的時機

a)緩存狀態:

基於開篇提到的我們之前文章,我們知道,可以把每次緩存穿透入庫查詢不存在的數據存儲一份狀態到緩存,這樣下次在查詢的時候就可以直接在緩存層面攔截。

這是一個正常的解決方法,對於很多應用場景都很適用。但是對於我們上述列舉的情景,這種方法會帶來一些不可避免的隱患。

關系是一種兩者之間的關聯,上面我們講到過,窮舉的關系數據相對於基數對象是一種量級的膨脹,所以以緩存不存在狀態來避免穿透會是一種成本無法控制的方式。

改進:雖然這種方式面對的是一個不確定量的緩存需求,但是我們可以通過對狀態設置較短的過期時間來一定程度的進行規避。

b)基於過濾器:

開篇介紹過布隆過濾器的特性,我們可以將每次查詢不存在的查詢放入過濾器,對於過濾器過濾判定結果,不存在的則進一步直接入庫查詢,判定存在的,則走常規的邏輯,查緩存,查庫。

說到這里,可能有人會有疑問,對於已判定不存在關系放入過濾器的,之后業務中產生了關系的,難道還要每次都直接入庫查詢嗎?

,確實是這種方式埋下的一個問題,但是相對於未應用過濾器之前,這種對於業務結果的正確性是沒有影響的,只是減慢了一部分查詢的響應時間。布隆過濾器的實現對刪除元素不太支持,雖然有些衍生的版本實現了這一功能,這里不再討論。對於上述這種情景,我們可以結合實際的業務數據測量,來定期的重建布隆過濾器來解決。

2、移除入庫查詢

其實,對於我們上述的這種緩存應用場景,我們為什么要入庫查詢呢?

因為緩存過期

按照我們通常的認知,緩存好像都必須要有過期時間,一來是為了保障數據一致性(緩存數據與庫數據),同時也是為了有效的控制緩存成本(熱點數據存留)。

但是,像我們列舉的這種量比不均的場景,就不可避免的引發穿透這種更加具有危害性的結果。

因此,此處,我們需要換一種方式來應用緩存。

我們可以將已有的關系數據全部緩存起來,設置不過期,同時移除后續的入庫查詢邏輯,所有的查詢全部由緩存數據來響應。

同時為了保障數據一致性,我們可以對數據變更做補償措施

數據的變更畢竟很少,相對於查詢畢竟有量級的差距。

因此,每次數據變更我們都可以進行一次數據同步(緩存和數據庫),當然,方式可以選擇同步或者異步

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM