展開
湖北國聯(lián)計算機科技有限公司
  • 首頁HOME
  • 公司簡介INTRODUCTION
  • 安全防御DEFENSE
  • 軟件開發(fā)SOFTWARE
  • 物聯(lián)網(wǎng)IOT
  • 運行維護SRE
  • 成功案例CASE
  • 聯(lián)系我們CONTACT
  • SOFTWARE |軟件開發(fā)

    后臺開發(fā)必備:每個程序員都應掌握的緩存技術
    來源:湖北國菱計算機科技有限公司-湖北國聯(lián)計算機科技有限公司-荊州網(wǎng)站建設-荊州軟件開發(fā)-政府網(wǎng)站建設公司 時間:2025-03-25

    緩存(Cache)是一種存儲技術,可以存儲數(shù)據(jù),以便快速獲取數(shù)據(jù)。緩存最重要的是兩個特性:存儲、快速獲取。緩存的本質(zhì):「用空間換時間」,用快速存儲的介質(zhì)保存數(shù)據(jù),以提升數(shù)據(jù)訪問的速度。
    在計算機的世界里,緩存被廣泛應用于硬件(如CPU 高速緩存、寄存器)和軟件中(如瀏覽器緩存、CDN、應用程序中的緩存等)。
    后臺中的緩存
    后臺開發(fā)中,緩存的使用場景一般有:

    ü 提升接口響應速度:緩存相比IO 請求、數(shù)據(jù)庫查詢速度要快得多,適當使用緩存提升響應速度

    ü 降低數(shù)據(jù)源服務的負載壓力:將需要高并發(fā)讀取的數(shù)據(jù)緩存起來,當相同請求進來時返回緩存數(shù)據(jù),減輕數(shù)據(jù)源服務(如數(shù)據(jù)庫、上游系統(tǒng))的負載壓力

    ü 減少計算資源的浪費:將需要復雜且耗時計算的結果緩存起來,減少相同請求導致的重復計算資源浪費

    01

    緩存策略

    緩存策略通常分為兩種,通讀緩存和旁路緩存。

    1.1 通讀(read-through)緩存

    在使用通讀緩存時,應用程序會嘗試從緩存中獲取數(shù)據(jù)。如果該數(shù)據(jù)已存在于緩存中,那么緩存會直接返回該數(shù)據(jù)。若緩存中并未包含所需數(shù)據(jù),那么緩存會自行訪問數(shù)據(jù)源來獲取數(shù)據(jù),并將獲取的數(shù)據(jù)返回給應用程序,同時將這份數(shù)據(jù)保存在緩存中。如此一來,當應用程序下次需要同樣的數(shù)據(jù)時,就能夠直接從read-through 緩存中獲取無需再次訪問數(shù)據(jù)源。

    通讀緩存的應用有很多,比如CDN:
    CDN(Content Delivery Network)即內(nèi)容分發(fā)網(wǎng)絡,是一種分布式的網(wǎng)絡架構。依賴于服務商提供的廣泛分布于各地的 CDN 服務器,通過把數(shù)據(jù)分發(fā)并緩存到各地的 CDN 服務器上,當用戶請求數(shù)據(jù)時,CDN 會匹配離用戶距離最近的節(jié)點并返回緩存數(shù)據(jù),以此來提高用戶訪問資源的速度。CDN 一般用來加速靜態(tài)資源的傳輸,比如圖片、CSS、HTML 等內(nèi)容。而動態(tài)的內(nèi)容,如搜索結果、單據(jù)信息等則不合適,

    這類數(shù)據(jù)需要應用服務器實時計算后才能返回。

    1.2 旁路(cache-aside)緩存


    與通讀緩存不同,旁路緩存不直接與數(shù)據(jù)源打交道。應用程序嘗試從旁路緩存獲取數(shù)據(jù),如果數(shù)據(jù)不存在,則返回空。應用程序自行請求數(shù)據(jù)源獲取數(shù)據(jù),并寫入旁路緩存。這樣下次相同的請求到達時,應用程序從旁路緩存中則會獲取到數(shù)據(jù)。


    通讀緩存和旁路緩存這兩種策略,一般來說都會靈活應用、互相包含。比如通讀緩存中,對數(shù)據(jù)的查詢和寫緩存,使用的就是旁路緩存策略。而該實現(xiàn)被整體封裝起來,對外表現(xiàn)的則是通讀緩存策略。

    02


    緩存類型
    在后臺服務中,緩存的類型可以分為本地緩存和分布式緩存。
    2.1 本地緩存(local cache)
    本地緩存,與應用程序的進程有相同的生命周期,存放于應用程序的堆空間(heap)中。

    ü 優(yōu)勢:使用簡單;無外部依賴;讀取速度快(無網(wǎng)絡IO 請求);

    ü 缺點:空間?。簯贸绦虻姆掌髻Y源有限,所以本地緩存的空間小;分布式一致性問題:如果后臺服務是分布式架構的,那么不同的服務實例之間的本地緩存可能會有差異;無法持久化:本地緩存會隨著進程結束而被銷毀,無法持久化。


    2.2 分布式緩存(remote cache)
    分布式緩存,也可理解為遠端緩存。使用外部的緩存服務,獨立部署,與應用程序解藕。

    ü 優(yōu)勢:空間充足:外部存儲一般空間都很充足;無分布式一致性問題:不同的服務實例連接同一個緩存服務,不存在一致性問題;主流的分布式緩存,如redis,支持數(shù)據(jù)持久化和恢復,當緩存服務掛了可以恢復數(shù)據(jù)。

    ü 缺點:引入外部依賴、需要部署和運維單獨的緩存服務。
    2.2.1 常見的緩存服務
    Redis

    ü 支持多種數(shù)據(jù)結構,如:list,set,zset,hash 等數(shù)據(jù)結構。

    ü 支持數(shù)據(jù)的持久化和恢復。

    ü 支持多種集群模式:主從復制、哨兵模式和Cluster 模式,保證高可用、容災恢復、易于擴展。

    ü 能提供毫秒級別的響應速度。

    ü Redis 6.0 引入了多線程 IO,之前是單線程模型。
    Memcache

    ü 主要支持簡單的鍵值對存儲。

    ü 不支持持久化和恢復。

    ü 集群:可以通過客戶端分片實現(xiàn)分布式存儲。

    ü 多線程,非阻塞IO 模式。

    ü 能提供毫秒級別的響應速度。


    選擇Redis 還是 Memcached 取決于具體的應用需求。如果需要一個輕量級、專注于緩存的解決方案,且不需要復雜的數(shù)據(jù)類型和持久化,Memcached 可能是更合適的選擇。而如果應用需要利用豐富的數(shù)據(jù)類型、持久化以及構建高可用的分布式系統(tǒng),Redis 將是更強大、更靈活的選擇。

    03


    緩存淘汰策略
    由于緩存的空間是有限的,如果緩慢的空間被使用完了,則需要淘汰舊的數(shù)據(jù),騰出空間給新的數(shù)據(jù)使用。緩存淘汰常用的幾種策略有如下幾種。
    3.1 FIFO(First In First Out)算法
    FIFO 算法是最簡單最好理解的,其策略是:先進先出,如果一個數(shù)據(jù)的寫入時間越早,說明將來被訪問的幾率越低。因此 FIFO 算法優(yōu)先淘汰最早寫入的數(shù)據(jù)。

    3.2 LRU(Least Recently Used)算法
    LRU 算法,即最近最少使用算法。如果一個數(shù)據(jù)最近被訪問了,那么將來被訪問的幾率越高。反之,如果一個數(shù)據(jù)很久都沒有訪問,那么將來被訪問的幾率越低。其淘汰策略就是:優(yōu)先淘汰最久沒有被使用到的數(shù)據(jù)。LRU 通常使用雙向鏈表+哈希表來實現(xiàn)。

    3.3 LFU(Least Frequently Used)算法
    LFU 算法,即最少使用算法。如果一個數(shù)據(jù)被訪問的次數(shù)越多,那么將來被訪問的幾率越高。反之,如果一個數(shù)據(jù)被訪問的次數(shù)越少,那么將來被訪問的幾率越小。其淘汰策略就是:優(yōu)先淘汰最少被使用的數(shù)據(jù)。LFU 算法可以使用小頂堆+哈希表來實現(xiàn)。


    大部分本地緩存的三方庫或緩存服務,都支持設置淘汰算法,無需自行實現(xiàn)。

    04


    緩存常見問題
    4.1 緩存與數(shù)據(jù)源的一致性
    緩存的數(shù)據(jù)是來自數(shù)據(jù)源的,當數(shù)據(jù)源被更新了,而緩存沒有被更新,后臺服務則會從緩存中取到臟數(shù)據(jù),這就有數(shù)據(jù)臟讀的問題。對于這個問題,主要的策略有兩種。
    4.1.1 過期失效
    每個寫入緩存中的數(shù)據(jù),都設置一個合適的過期時間,在有效期內(nèi)都返回緩存的數(shù)據(jù)。當緩存數(shù)據(jù)過期失效,則會回源到數(shù)據(jù)源,重新緩存最新的數(shù)據(jù)。這種情況會有數(shù)據(jù)臟讀的問題,不過采用過期失效的數(shù)據(jù),一般是更新不頻繁的數(shù)據(jù),比如用戶信息、熱門信息等,存在一定的數(shù)據(jù)延遲是可以接受的。
    4.1.2 主動更新
    當數(shù)據(jù)源的數(shù)據(jù)更新了,程序主動去更新緩存數(shù)據(jù),保證緩存中的數(shù)據(jù)始終是最新的。這種策略,適合對數(shù)據(jù)的時效性要求很高的數(shù)據(jù),比如庫存、余額等等。主動更新的代價則是代碼的復雜度增加,所有涉及數(shù)據(jù)更新的操作,都需要更新其緩存數(shù)據(jù)。
    無論是過期失效還是主動更新,首先應該分析當前場景對數(shù)據(jù)的時效性要求是否很高?如不是,過期失效足矣。如果是,需要衡量主動更新的代價能否接受,比如代碼復雜度增加。否則是否可以通過縮短失效時間而采取過期失效策略來折中處理。
    4.2 緩存雪崩
    緩存雪崩是指在同一時間點后臺服務中的緩存大量過期失效,當服務的并發(fā)量很高時,大量的數(shù)據(jù)請求同時到達數(shù)據(jù)源服務(比如數(shù)據(jù)庫或其他服務),引起數(shù)據(jù)源服務的瞬時負載增大,甚至崩潰。
    引起緩存雪崩的原因一般有兩種:

    ü 一是大量的緩存key 在同一時間失效

    ü 二是緩存服務不可用,請求都被透傳到數(shù)據(jù)庫。



    解決辦法:

    ü 設置合理的緩存失效時間:合理設置過期時間,分散緩存的失效時間,避免緩存在同一時間失效。

    ü 保證緩存服務的高可用:使用獨立的緩存服務,盡量使用緩存集群,保證緩存服務的高可用和容災恢復。

    4.3 緩存穿透
    緩存穿透是指同一時間大量的空值請求到達后臺服務,空值請求是指查詢數(shù)據(jù)源后無數(shù)據(jù)的請求,由于數(shù)據(jù)源返回空數(shù)據(jù),所以緩存層沒有將空值保存,導致空值請求必然會穿透緩存層,透傳到數(shù)據(jù)源。
    引起緩存穿透的原因,一般有:

    ü 未對請求參數(shù)進行合理的校驗和攔截。

    ü 被精心構造的惡意請求攻擊。


            解決辦法:

    ü 設置合理的參數(shù)校驗:通過設置合理的校驗規(guī)則,比如id 范圍、名稱正則規(guī)則等,對不合理或空值請求的參數(shù)的進行過濾和攔截。

    ü 緩存空值處理:即使數(shù)據(jù)源返回空值,也在緩存層將其保存起來。可能對其數(shù)值設置一些標記,比如value=-1 等等,方便服務識別為空值。同時,也可以為空值的緩存設置一個較短的失效時間。
    4.4 緩存擊穿
    緩存擊穿是指某個熱點數(shù)據(jù)的緩存失效了,然后同一時間有大量的請求訪問該熱點數(shù)據(jù),由于緩存失效,這些請求同時被透傳到數(shù)據(jù)源服務,導致數(shù)據(jù)源的負載增加,甚至崩潰。
    引起緩存擊穿的原因,一般是:熱點數(shù)據(jù)的緩存失效時,高并發(fā)請求同時訪問該數(shù)據(jù)。


    解決辦法:

    ü 使用互斥鎖或者分布式鎖,對數(shù)據(jù)的回源操作進行上鎖,保證同一時刻只有一個請求被透傳到數(shù)據(jù)源服務。

    ü 熱點數(shù)據(jù)的緩存永不過期,由數(shù)據(jù)源主動更新緩存。

    ü 熱點數(shù)據(jù)預加載:在緩存數(shù)據(jù)將要過期時,由后臺服務主動更新熱點數(shù)據(jù)緩存,防止緩存失效。

    05

    總結
    本文詳細地介紹了后臺開發(fā)中的緩存技術,希望能對你的日常工作有所幫助和啟發(fā)。熟練掌握各種緩存策略和機制,解決緩存問題,對于程序員而言至關重要,可以在很大程度上提升后臺開發(fā)的效率、穩(wěn)定性和用戶體驗。


    荊州地區(qū)政府網(wǎng)站建設 解決方案 專業(yè)團隊 騰訊第三方平臺 地址:湖北省荊州市沙市區(qū)荊沙大道楚天都市佳園一期C區(qū)29棟112       地址:湖北省松滋市新江口街道才知文化廣場1幢1146-1151室     郵編:434200 聯(lián)系電話:0716-6666211     網(wǎng)站編輯部郵箱:business@gl-ns.com 鄂公網(wǎng)安備 42100202000212號 備案號:鄂ICP備2021015094號-1     企業(yè)名稱:湖北國菱計算機科技有限公司