日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小白都能看懂的缓存入门

發(fā)布時間:2025/3/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小白都能看懂的缓存入门 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

緩存是程序員必須了解的技術,無論是前端、后端還是客戶端,大到復雜的系統(tǒng)架構,小到 CPU 或是芯片,都少不了緩存的影子。

下面只需 5 分鐘,帶你入門緩存技術。

什么是緩存?

緩存(Cache)本意是指可以進行高速數(shù)據(jù)交換的存儲器,通俗點來說,就是通過將數(shù)據(jù)提前存放到內存,以提高訪問速度

在我們設計程序或算法時,有兩個基本指標,即時間復雜度空間復雜度。有時,我們的程序無法同時滿足二者,就只能以時間換空間,或者以空間換時間。緩存是以空間換時間思想的典型應用,犧牲一部分內存空間,能夠得到數(shù)百倍的讀取性能提升。

緩存最常見的數(shù)據(jù)結構是鍵值對(Key/Value),類似字典,即一個 Key 對應一個 Value,訪問緩存時通過 Key 獲取 Value。

為什么需要緩存?

最簡單的后端系統(tǒng)只需要一個應用服務(比如 Tomcat)和持久化存儲數(shù)據(jù)的數(shù)據(jù)庫(如 MySQL),對于一個訪問量很小的系統(tǒng)來說,這樣的架構就足夠了。

但隨著系統(tǒng)的用戶數(shù)和訪問量的提升,數(shù)據(jù)庫會收到越來越多的并發(fā)請求。由于數(shù)據(jù)庫是從磁盤中讀取數(shù)據(jù),性能較低,隨著請求數(shù)的增多,數(shù)據(jù)庫受到的壓力會越來越大。由于應用訪問數(shù)據(jù)庫的連接數(shù)有限,當數(shù)據(jù)庫的處理能力跟不上請求數(shù)時,新的請求將排隊等待,從而導致我們的后臺程序也會阻塞。當并發(fā)請求數(shù)持續(xù)增大時,數(shù)據(jù)庫甚至會掛掉!歐豁,完蛋。

因此,我們需要性能更高的讀取數(shù)據(jù)方式,能夠幫助數(shù)據(jù)庫分擔壓力,緩存登場了

可以在數(shù)據(jù)庫之上增加一層緩存,當后臺程序首次讀取數(shù)據(jù)時,將得到的數(shù)據(jù)存入緩存中,那么后續(xù)的請求要讀取相同數(shù)據(jù)時,只需從緩存中讀取即可。由于緩存是將數(shù)據(jù)存入內存中,讀取速度非???#xff0c;在成功提升性能的同時,替數(shù)據(jù)庫分擔了大量的壓力。

因此想要提升系統(tǒng)的整體性能,緩存是不可或缺的。

緩存類別

可以將緩存分為兩種類型。

本地緩存

直接運行在應用程序本地的緩存組件。

比如 JVM 中的 Map 數(shù)據(jù)結構,可以作為最簡單的數(shù)據(jù)緩存:

class LocalCache {private static Map<String, Object> cache = new HashMap<>();private LocalCache() {}public static void put(String key, Object value) {cache.put(key, value);}public static Object get(String key) { return cache.get(key);}}

如果你的應用程序只需要運行在一臺服務器上,并且多個應用程序之間不需要共享緩存的數(shù)據(jù)(比如用戶 token),可以直接采用本地緩存,訪問緩存時不需要通過網(wǎng)絡傳輸,非常地方便迅速。

但是本地緩存會和你的應用程序強耦合,應用程序停止,本地緩存也就停止了。而且如果是在分布式場景下,多個機器都要使用緩存,此時如果在每個服務器上單獨維護一份本地緩存,不僅無法共享數(shù)據(jù),而且非常浪費內存(因為每臺機器可能緩存了相同的數(shù)據(jù))。

為解決緩存數(shù)據(jù)共享的問題,可以使用分布式緩存。

分布式緩存

分布式緩存是指獨立的緩存服務,不和任何一個具體的應用耦合,可以獨立運行并搭建緩存集群。類似數(shù)據(jù)庫,所有的應用程序都可以連接同一個緩存服務以獲取相同的緩存數(shù)據(jù)。

除了數(shù)據(jù)共享外,分布式緩存的優(yōu)點還有很多。比如不需要每臺機器單獨維護緩存、可以集中管理緩存和整體管控分析、便于擴展和容錯等。但是應用必須要通過網(wǎng)絡訪問分布式緩存服務,會產(chǎn)生額外的網(wǎng)絡開銷成本;并且每臺機器都有可能會對整個分布式緩存服務產(chǎn)生影響,而一旦分布式緩存掛了,所有的應用都可能出現(xiàn)癱瘓(緩存雪崩)。

多級緩存

上述兩種緩存沒有絕對的優(yōu)劣,要根據(jù)實際的業(yè)務場景進行選型。其實還可以將本地緩存與分布式緩存相結合,形成多級緩存服務,架構如下:

當首次查詢時(不存在緩存),會同時將數(shù)據(jù)寫入本地緩存和分布式緩存。之后的查詢優(yōu)先查詢分布式緩存,而如果分布式緩存宕機,則從本地緩存獲取數(shù)據(jù)。通過多級緩存機制,能夠起到兜底的作用,即使緩存掛掉,也能支撐應用運行一段時間。

緩存淘汰策略

下面我們思考一個問題,如何去實現(xiàn)一個本地緩存呢?

剛剛提到的 Map 數(shù)據(jù)結構是一個思路,但是和我們自己的電腦存儲文件、或者是和 JVM 存儲對象一樣,內存當然不是無限的。因此在實現(xiàn)緩存時,必須要設計一套緩存淘汰策略,按照某種機制回收緩存占用的內存,保證緩存數(shù)據(jù)不會無限地增長直到撐爆內存。

下面介紹幾種常見的緩存淘汰策略,關鍵問題就是當緩存空間已滿時,應該選擇哪些緩存進行刪除。

LRU 最近最少使用

LRU(Least Recently Used)是最經(jīng)典的內存淘汰策略,其設計原則是 “如果一個數(shù)據(jù)在最近一段時間沒有被訪問到,那么在將來它被訪問的可能性也很小”。即根據(jù)數(shù)據(jù)的最近訪問時間來進行淘汰。缺點是可能會由于一次冷數(shù)據(jù)的批量查詢而誤刪除大量的熱點數(shù)據(jù)。

近似 LRU 算法

類似 LRU 算法,只是每次隨機選擇一批數(shù)據(jù)進行 LRU 淘汰,而不是全量 LRU 運算,犧牲部分準確度,以提升算法執(zhí)行效率。

Redis 3.0 之后對其進行了優(yōu)化,維護了一個侯選池,將隨機選擇的數(shù)據(jù)放入侯選池中進行 LRU 運算。當侯選池放滿后,新隨機的數(shù)據(jù)會替換掉池中最近被訪問的數(shù)據(jù)。

TTL 超時時間

TTL(Time To Live)是指用戶為緩存設置的過期時間,當前時間到達過期時間時,將刪除緩存;如果緩存空間已滿,則優(yōu)先淘汰最接近過期時間的數(shù)據(jù)。

LFU 最少使用

LFU(Least Frequently Used)策略會記錄每個緩存數(shù)據(jù)的最近訪問次數(shù)(頻率),并優(yōu)先清除使用次數(shù)較少的數(shù)據(jù)。這種算法存在的顯著缺點是,最新寫入的數(shù)據(jù)由于訪問次數(shù)少,常常剛被緩存就刪除了。

FIFO 先進先出

FIFO(First In First Out)先進先出策略會將數(shù)據(jù)按照寫入緩存的順序進行排隊,當緩存空間不足時,最先進入緩存的數(shù)據(jù)會被優(yōu)先刪除。是一種比較死板的策略,不考慮數(shù)據(jù)熱度,可能會淘汰大量的熱點數(shù)據(jù),但是實現(xiàn)起來相對容易。

Second-Chance

對 FIFO 算法的改進,給每個緩存數(shù)據(jù)添加一個引用標志,當數(shù)據(jù)被訪問時,設置其標志位為 1。

當緩存空間不足時,會檢測隊列首部(最先寫入緩存)數(shù)據(jù)的引用標志位,如果為 1,表示被訪問過,則重置標志位為 0 并且重新加入隊列尾部;如果為 0,表示未被訪問過,直接淘汰。

相對 FIFO 算法來說,更加靈活,降低了淘汰熱點數(shù)據(jù)的風險。

Random 隨機

隨機淘汰策略,沒啥好說的,一般不建議使用。

還有一些其他的策略,比如優(yōu)先淘汰占用空間最大的數(shù)據(jù)等,不再贅述。

緩存實現(xiàn)

要想自己設計一個優(yōu)秀的緩存,還是有難度的,不止是用一個 Java 的數(shù)組或者集合類那么簡單。幸運的是,有很多現(xiàn)成的類庫、框架和中間件可供我們直接使用。下面介紹一些優(yōu)秀的緩存實現(xiàn)。

Caffeine

Caffeine 是基于 Java8 的近似最佳的高性能本地緩存庫。提供了靈活的構造器 API,能夠輕松地創(chuàng)建緩存對象,并且組合各種特性。可謂是進程緩存之王。

地址:https://github.com/ben-manes/caffeine/

Guava Cache

Guava 是 Google 開源的 Java 工具包,而 Guava Cache 是其中的本地緩存實現(xiàn),提供了 time-based、size-based 等多種緩存淘汰策略,使用起來非常方便。

地址:https://github.com/google/guava/

Ehcache

Ehcache 是 Java 實現(xiàn)的開源緩存框架,特性齊全,成熟輕量,并且支持通過 RMI 等方式實現(xiàn)可擴展的分布式緩存。

地址:http://www.ehcache.org/

Memcached

開源的高性能分布式內存 K/V 緩存系統(tǒng),支持主流語言的 API,適合存儲小塊的數(shù)據(jù),可以利用多核 CPU。缺點是不支持持久化。

地址:http://memcached.org/

Redis

知名的 K/V 存儲系統(tǒng),適用于分布式緩存,支持多種數(shù)據(jù)結構、讀寫性能極高,并且可以搭建高可用集群、易擴展、支持持久化。還能通過 Lua 腳本實現(xiàn)原子性。

Spring Cache

Spring Cache 提供了抽象的緩存接口,幫助我們更好地使用緩存,底層可以選擇不同的緩存實現(xiàn),比如 Caffine 或者 Guava Cache。

沒有銀彈

緩存雖然具有很多優(yōu)點,但也不是萬能的。引入緩存后,還要考慮到緩存刪除、緩存更新、緩存穿透、緩存擊穿、緩存雪崩等問題。引入的緩存級數(shù)越多,數(shù)據(jù)不一致的風險就越大。因此,在架構設計時,要根據(jù)實際的業(yè)務需求來是否使用緩存、選用何種緩存。

畢竟,沒有銀彈。

有道無術,術可成;有術無道,止于術

歡迎大家關注Java之道公眾號

好文章,我在看??

新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

總結

以上是生活随笔為你收集整理的小白都能看懂的缓存入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。