對緩存的一些簡單理解

1. 緩存

提起 緩存(cache),一般會想到cpu高速緩存、內存緩存。緩存的本質是將部分的數據使用另一種存取速度更快的介質存儲,使系統更快的操作和響應。比如我們將部分的數據從磁盤放到內存中,直接操作內存的數據,這樣比從磁盤讀取數據要快上幾千幾萬倍。

既然高速的介質這麼好用,那爲什麼不全部使用高速的介質呢,這裏直接用我們平常用的內存和磁盤做對比。

首先是價格差異巨大,目前市場價磁盤的價格大概在幾毛錢到幾塊錢1GB,而內存則需要幾十塊,甚至接近百塊1GB,兩者價格相差甚遠。全部使用內存來存儲數據,這口袋的錢頂不住啊。如果是cpu高速緩存的造價跟磁盤比,那根本就是一個天一個地,而且CPU的緩存是按MB單位來算的。英特爾i9-9900K處理器,緩存16MB。

另一個很重要的原因是內存和磁盤的定位不一樣,內存是爲了系統中能夠快速處理數據而設立的,它是即時的,並不具有持久性。開機通電之後內存纔會起作用,一旦關機或者停電,數據就消失。這個數據不能永久保存,這也不不是個辦法啊。而磁盤就不一樣,它雖然比較慢,但是數據是持久保存的。

因爲內存和磁盤的定位和特點,導致了它們各自有適合的使用場景,一般情況都是共同使用的。

2.使用緩存的問題

這裏開始,只講內存和數據庫相關的東西,緩存數據指的是存儲在內存中的副本數據。

平時我們編寫的服務器中,因爲內存大小的限制,會將常用的部分數據從數據庫緩存到內存中,以此來加快服務器的處理速度,增大服務的吞吐量。但是緩存的使用並不是那麼簡單的,裏面含有很多坑,就等着你們來踩。

1. 數據一致性問題

使用緩存最大的問題就是 數據不一致,在複雜的環境下,就更明顯,更難處理。

緩存中的數據是數據庫的副本,如果是隻讀操作,那麼不會出現什麼問題,如果涉及到修改刪除等操作,就會存在數據不一致的問題。

舉個例子,一個用戶的名稱爲nameA,此時他將名稱改爲nameB,這時只操作緩存或者數據庫,都會導致緩存和數據庫數據不一致的問題。

那麼有人就說了,同時操作數據庫和緩存不就可以了。思路是可以的,但是在併發條件下實現起來可是會出現問題的。

假設有兩個線程t1和t2,線程t1是修改操作,線程t2是讀取操作,線程t1先修改了數據庫,還沒來得及修改緩存,此時線程t2讀取緩存數據,那麼t2讀取的數據就不是最新的數據。
在這裏插入圖片描述

那麼這時候又有人說,加個鎖不就好了,可以用讀寫鎖,並且將鎖的粒度變小,以用戶id來作爲鎖。在讀的操作所有線程都可以讀,但是寫操作時,只有一個線程可以操作,這樣既保證了數據一致性,又能滿足服務器的高性能要求。

這是保證緩存一致性的一個解決方案,但是並不是說這種方法就是完美的,也不一定適合其他應用場景。

在使用緩存的時候,沒有最完美最通用的解決方案,只有最適合該場景的方案。

2. 命中率

緩存畢竟只是部分數據的副本,在數據讀取的時候,首先會讀取緩存中的數據,如果緩存中沒有,就會去讀取數據庫的數據。如果說請求需要的數據緩存中都沒有,這時候緩存就沒有一點作用。在平時使用緩存的時候,要評估哪些是常用的數據。

在提高命中率時,有一個較爲通用的方法。當一個數據不在緩存中時,此時線程會讀取數據庫,在讀取完後將該數據存入緩存中,下次讀取的時候,直接讀取緩存就行了。

3. 空間整理

內存的空間是比較小的,在使用的過程中緩存的數據會越來越多,這時候就要進行數據清理了,將不常用,不必要的數據刪除。那麼用什麼方法找出不常用的數據呢,這裏列出比較常用的幾種緩存清除策略。

FIFO ( first in first out)

先進先出策略,很簡單粗暴,在清除的時候,最開始存入的數據,將先被清除。這在某些特定場合下是可以的,但是一般情況下使用這個策略會顯得程序非常死板,不夠"智能"。

LFU(less frequently used)

最少使用策略。指的是某些數據使用次數最少,將最先被清除。常用的做法是標記數據的命中次數,以此來判斷數據是否比較常用。

一般來說命中次數還得加上一個時間段的限制,記錄某個時間段內數據的命中次數,防止出現某些數據在一開始是常用,後來根本不會被使用到。

比如某個玩家一開始沉迷某艦娘,畢竟那麼大,哦不對,是那麼好玩,該玩家天天登錄,理所當然的他個人信息命中次數很高。但某一天他氪不動也肝不動,棄坑了,之後都沒登錄過,那麼這個數據其實是不常用的了。

LRU (less recently used)

最近最少使用策略,標記數據最近一次使用的時間,在清除時,將釋放太久沒有被使用的數據。這個適用熱點數據場景中。

設置過期時間

添加緩存的時候,就給該數據標記存活時間,超過了這個時間,該數據將被釋放。這個Redis中挺經常用到的。

隨機清理

如它的名稱一樣,清除的時候隨機清理。多麼粗暴的清理方法,可能會有程序會使用,的吧(我並不確定)。我的閱歷少,還沒見過使用這種方法的應用場景,如果有,麻煩告訴我一聲。

4. 緩存雪崩

緩存雪崩是指大量的請求直接透過了緩存層請求數據庫(緩存穿透),導致數據庫壓力過大,嚴重的會出現數據庫宕機。

緩存穿透出現可能是由於原緩存過期(或其他原因被清除),新的緩存未存放,導致請求穿透到數據庫。也有可能是服務器剛啓動,還來不及緩存數據。

解決方案就是要避免大量緩存在同一時刻過期,還有在服務器啓動時,將請求量從小到大的引導到服務器中。

3. 總結

爲什麼要使用緩存

因爲它速度快,僅此而已

使用緩存的問題

這裏就不總結了,看文章吧

其實還想寫一寫在具體的業務場景中緩存的設計以及在設計時考慮和抉擇,不過寫起來挺長的,還是放到另一篇文章裏好了。

參考文章

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