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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

浅谈缓存

發布時間:2024/4/15 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 什么是緩存

緩存有很多種,從 CPU 緩存、磁盤緩存到瀏覽器緩存等,本文所說的緩存,主要針對后端系統的緩存。也就是將程序或系統經常要使用的對象存在內存中,以便在使用時可以快速調用,也可以避免加載數據或者創建重復的實例,以達到減少系統開銷,提高系統效率的目的。

2. 為什么要用緩存

我們一般都會把數據存放在關系型數據庫中,不管數據庫的性能有多么好,一個簡單的查詢也要消耗毫秒級的時間,這樣我們常說的 QPS 就會被數據庫的性能所限制,我們想要提高QPS,只能選擇更快的存儲設備。

在日常開發有這樣的一種場景:某些數據的數據量不大、不經常變動,但訪問卻很頻繁。受限于硬盤 IO 性能或者遠程網絡等原因,每次都直接獲取會消耗大量的資源。可能會導致我們的響應變慢甚至造成系統壓力過大,這在一些業務上是不能忍的,而緩存正是解決這類問題的神器。

但是有一點需要注意,就是緩存的占用空間以及緩存的失效策略,下文也會提到。

使用緩存的場景

對于緩存來說,數據不常變更且查詢比較頻繁是最好的場景,如果查詢量不夠大或者數據變動太頻繁,緩存也就是失去了意義。

3. 緩存的使用

日常工作使用的緩存可以分為內部緩存和外部緩存。

內部緩存一般是指存放在運行實例內部并使用實例內存的緩存,這種緩存可以使用代碼直接訪問。

外部緩存一般是指存放在運行實例外部的緩存,通常是通過網絡獲取,反序列化后進行訪問。

一般來說對于不需要實例間同步的,都更加推薦內部緩存,因為內部緩存有訪問方便,性能好的特點;需要實例間同步的數據可以使用外部緩存。

下面對這兩種類型的緩存分別的進行介紹。

3.1 內部緩存

為什么要是用內部緩存

在系統中,有些數據量不大、不常變化,但是訪問十分頻繁,例如省、市、區數據。針對這種場景,可以將數據加載到應用的內存中,以提升系統的訪問效率,減少無謂的數據庫和網路的訪問。

內部緩存的限制就是存放的數據總量不能超出內存容量,畢竟還是在 JVM 里的。

最簡單的內部緩存 - Map

如果只是需要將一些數據緩存起來,避免不必要的數據庫查詢,那么 Map 就可以滿足。

對于字典型的數據,在項目啟動的時候加載到 Map 中,程序就可以使用了,也很容易更新。

// 配置存放的Map

Map<String, String> configs = new HashMap<String, String>(); // 初始化或者刷新配置的Map public void reloadConfigs () { Map<String, String> m = loadConfigFromDB(); configs = m;} // 使用 configs. getOrDefault ( "auth.id" , "1" );

功能強大的內部緩存 - Guava Cache / Caffeine

如果你需要緩存有強大的性能,或者對緩存有更多的控制,可以使用 Guava 里的 Cache 組件。

它是 Guava 中的緩存工具包,是非常簡單易用且功能強大的 JVM 內緩存,支持多種緩存過期策略。

LoadingCache<String, String> configs = CacheBuilder.newBuilder().maximumSize(1000) // 設置最大大小.expireAfterWrite(10, TimeUnit.MINUTES) // 設置過期時間, 10分鐘.build(new CacheLoader<String, String>() {// 加載緩存內容public String load(String key) throws Exception {return getConfigFromDB(key);}public Map<String, String> loadAll() throws Exception {return loadConfigFromDB();}});//CacheLoader.loadAll// 獲取某個key的值try {return configs.get(key);} catch (ExecutionException e) {throw new OtherException(e.getCause());}// 顯式的放入緩存configs.put(key, value)// 個別清除緩存configs.invalidate(key)// 批量清除緩存configs.invalidateAll(keys)// 清除所有緩存項configs.invalidateAll()

本地緩存的優點:

  • 直接使用內存,速度快,通常存取的性能可以達到每秒千萬級

  • 可以直接使用 Java 對象存取

本地緩存的缺點:

  • 數據保存在當前實例中,無法共享

  • 重啟應用會丟失

Guava Cache 的替代者 Caffeine

Spring 5 使用 Caffeine 來代替 Guava Cache,應該是從性能的角度考慮的。從很多性能測試來看 Caffeine 各方面的性能都要比 Guava 要好。

Caffeine 的 API 的操作功能和 Guava 是基本保持一致的,并且 Caffeine 為了兼容之前 Guava 的用戶,做了一個 Guava 的 Adapter, 也是十分的貼心。

如果想了解更多請參考:是什么讓 Spring 5 放棄了使用 Guava Cache?

3.2 外部緩存

最著名的外部緩存 - Redis / Memcached

也許是 Redis 太有名,只要一提到緩存,基本上都會說起 Redis。但其實這類緩存的鼻祖應該是 LiveJournal 開發的 Memcached。

Redis / Memcached 都是使用內存作為存儲,所以性能上要比數據庫要好很多,再加上Redis 還支持很多種數據結構,使用起來也挺方便,所以作為很多人的首選。

Redis 確實不錯,不過即便是使用內存,也還是需要通過網絡來訪問,所以網絡的性能決定了 Reids 的性能;

我曾經做過一些性能測試,在萬兆網卡的情況下,對于 Key 和 Value 都是長度為 20 Byte 的字符串的 get 和 set 是每秒10w左右的,如果 Key 或者 Value 的長度更大或者使用數據結構,這個會更慢一些;

作為一般的系統來使用已經綽綽有余了,從目前來看,Redis 確實很適合來做系統中的緩存。

如果考慮多實例或者分布式,可以考慮下面的方式:

  • Jedis 的 ShardedJedis( 調用端自己實現分片 )

  • twemproxy / codis( 第三方組件實現代理 )

  • Redis Cluster( 3.0 之后官方提供的集群方案 )

這些方案各有特點,這次先不展開討論,有興趣的可以先研究一下。

Redis有很多優點:

  • 很容易做數據分片、分布式,可以做到很大的容量

  • 使用基數比較大,庫比較成熟

同時也有一些缺點:

  • Java 對象需要序列化才能保存

  • 如果服務器重啟,再不做持久化的情況下會丟失數據,即使有持久化也容易出現各種各樣的問題

4. 緩存的更新策略

使用緩存時,更新策略是非常重要的。最常見的緩存更新策略是 Cache Aside Pattern:

  • 失效:應用程序先從 cache 取數據,沒有得到,則從數據庫中取數據,成功后,放到緩存中。

  • 命中:應用程序從 cache 中取數據,取到后返回。

  • 更新:先把數據存到數據庫中,成功后,再讓緩存失效。

不管是內部緩存還是外部緩存,都可以使用這樣的更新策略,如果緩存系統支持,也可以通過設置過期時間來更新緩存。

更多的更新策略可以參考左耳朵耗子的這篇緩存更新的套路。

5. 緩存使用常見誤區

序列化方案的選擇

序列化的選擇,盡量避免使用 Java 原生的機制,因為原生的序列化依賴 serialVersionUID 來判斷版本,如果改變就無法正常的反序列化。

一般推薦使用 Json 或者 Hessian、ProtoBuf 等二進制方式。

緩存大對象

在緩存中存放大對象,存取的代價都比較高。實際使用時,往往只是需要其中的一部分,這樣會導致每一次讀取都消耗更多的網絡和內存資源,也會浪費緩存的容量。

當然如果每次都是用完整的對象,這樣做是沒有問題的。

使用緩存進行數據共享

使用緩存來當作線程甚至進程之間的數據共享方式,會讓系統間產生隱形的依賴,并且也可能會產生一些競爭,常常會發生問題。所以不推薦使用這種方式來共享數據。

沒有及時更新或者刪除緩存中已經過期或失效的數據

這個理解起來就很簡單了,如果沒有及時更新或者刪除,就有可能讀取到錯誤的數據,從而導致業務的錯誤。

對于支持設置過期時間的緩存系統,可以對每一個數據設置合適的過期時間,來盡量避免這樣的情況。

總結

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

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