Java 快取是一種用於在臨時儲存區域(稱為快取)中儲存和管理經常訪問的資料的技術,以提高應用程式效能。快取透過保持副本隨時可用,有助於減少獲取或計算資料所需的時間和資源。
在 Java 中,快取可以在各個級別實現,包括:
- 記憶體快取: Java 使用Guava Cache或CaffeineHashMap等資料結構或專用庫提供記憶體快取機制。這些允許開發人員將鍵值對儲存在記憶體中,從而使資料檢索比從原始來源獲取更快。
- 分散式快取:在分散式系統中,快取可以跨多個節點擴充套件以共享快取資料。Ehcache、Apache Ignite、Oracle Coherence、Infinispan、VMware GemFire或Redis 等庫和平臺提供分散式快取解決方案,支援在應用程式的不同例項之間高效共享快取資料。
- 應用程式級快取:許多 Java 框架和庫都提供內建快取機制。例如,Spring@Cacheable提供了全面的快取抽象,允許開發人員透過簡單地使用快取註釋(如、 和)來註釋方法,從而輕鬆地將快取整合到他們的應用程式中@CachePut,並@CacheEvict在方法級別控制快取行為。
- HTTP 快取:對於 Web 應用程式,Java 支援使用Cache-Control和等標頭的 HTTP 快取機制ETag。這些標頭使瀏覽器和 Web 伺服器能夠快取影像、樣式表和指令碼等資源,從而減少在後續請求時重新下載它們的需要。
- 資料庫快取:可以在資料庫級別應用快取來儲存頻繁訪問的查詢結果。Java 應用程式通常利用Hibernate等技術進行物件關係對映,其中包括快取功能。
Java 快取在最佳化應用程式效能方面發揮著至關重要的作用,特別是在資料檢索或計算資源密集型的場景中。必須根據應用程式的具體需求仔細設計和配置快取策略,以在提高效能和高效資源利用之間取得平衡。
JCache API (JSR 107)
JSR-107,通常稱為 JCache,是一個用於快取 API 和標準化快取註釋的 Java 規範。JCache 的目標是為 Java 應用程式提供一種與快取系統互動的通用方法,從而促進跨不同快取提供程式(如上面提到的快取提供程式)的可移植性。
JCache 的主要功能包括:
- API標準化: JCache定義了一組用於與快取互動的標準介面和類。它不依賴於特定的快取實現。相反,它允許整合符合規範的多個快取提供程式。
- 註解: JCache 引入了諸如@CacheResult、@CachePut、 之類的註解,@CacheRemove可用於以宣告方式控制快取行為。這些註釋與Spring等框架中的註釋類似。
- 基本快取操作: JCache 支援基本快取操作,包括從快取中放入、獲取和刪除條目。它提供了執行這些操作的標準化方法,無論底層快取提供程式如何。
- 配置:該規範定義了配置快取設定的標準化方法,例如快取大小、逐出策略和過期時間。這使得管理和調整不同實現中的快取行為變得更加容易。
- 與 Java EE 和 SE 整合: JCache 旨在與 Java EE(企業版)和 Java SE(標準版)環境無縫整合。這確保了應用程式可以在不同的 Java 平臺上使用相同的快取 API。
使用 JCache 等標準 API,開發人員可以在不同的快取實現之間切換,並選擇最適合其需求的快取解決方案,而無需對應用程式進行最少的程式碼更改。此外,它還提高了生產力,因為它確保學習曲線更小,因為它僅限於 JCache 作為標準的知識,而不是每個供應商實施的具體情況。
JCache 案例
要使用 JCache 建立一個簡單的“Hello World”示例,您首先需要在專案中包含 JCache API 和特定的快取提供程式。
<dependencies> |
以下示例設定一個快取,放入“Hello, World!” 問候語進入快取,檢索它,並將其列印到控制檯。
import javax.cache.Cache; |
javax.cache.Cache介面
javax.cache.Cache介面是 Java 快取 API 的基本部分。它代表一個快取,是鍵值對的臨時儲存區域,可以快速儲存和檢索資料。它提供了儲存、檢索和操作快取資料的方法。它抽象了底層快取實現,允許開發人員透過通用介面與不同的快取提供程式進行互動。
- V get(K key) 從快取中檢索與指定鍵關聯的值,或者null如果未找到該鍵。
- void put(K key, V value) 將指定值與快取中的指定鍵相關聯。
- boolean containsKey(K key) 檢查快取中是否包含指定鍵的條目。
- V getAndPut(K key, V value) 檢索與指定鍵關聯的當前值,然後使用新值更新該值。
- void remove(K key) 從快取中刪除指定鍵的條目(如果存在)。
- boolean remove(K key, V oldValue) 僅當指定鍵當前對映到指定值時,才從快取中刪除該條目。
- void removeAll(Set<? extends K> keys) 從快取中刪除多個鍵的條目。
- void removeAll() 從快取中刪除所有條目。
- void putAll(Map<? extends K, ? extends V> entries) 將多個鍵值對與快取關聯。
- boolean putIfAbsent(K key, V value) 如果指定鍵尚未與值關聯,則將指定值與快取中的指定鍵關聯。
- void clear() 清除快取,刪除所有條目。
- void close() 關閉快取,釋放與其關聯的所有資源。
javax.cache.CacheManager
javax.cache.CacheManager介面負責管理快取環境中的快取及其配置。它提供了建立、檢索和管理快取的方法,以及訪問配置和統計等特定於快取的功能。
- CachingProvider getCachingProvider() 檢索CachingProvider與 this 關聯的CacheManager.
- void close() 關閉它CacheManager並釋放與其關聯的所有資源。
- void destroyCache(String cacheName) 銷燬由其名稱指定的快取。
- boolean isClosed() 檢查這是否CacheManager已關閉。
- boolean isSupported(OptionalFeature feature) 檢查 this 是否支援指定的可選功能CacheManager。
- void enableManagement(String cacheName, boolean enabled) 啟用或禁用對其名稱指定的快取的管理(統計和監視)。
- void enableStatistics(String cacheName, boolean enabled) 啟用或禁用由名稱指定的快取的統計資訊收集。
- void createCache(String cacheName, Configuration<K,V> configuration) 建立具有指定名稱和配置的快取。
- void destroyCache(String cacheName) 銷燬由其名稱指定的快取。
- C getCache(String cacheName, Class<K> keyType, Class<V> valueType) 按名稱檢索快取,指定鍵和值型別。
- Iterable<String> getCacheNames() 檢索由此管理的快取名稱的可迭代集合CacheManager。
- ClassLoader getClassLoader() 檢索ClassLoader由此管理的快取所使用的內容CacheManager。
在快取環境中管理快取及其配置的基本功能。開發人員可以根據應用程式的需要使用這些方法來建立、訪問和配置快取。
javax.cache.spi.CachingProvider介面
javax.cache.spi.CachingProvider介面充當建立和訪問快取相關實體(例如CacheManager例項)的工廠。它充當應用程式和底層快取實現之間的抽象層。
- CacheManager getCacheManager() CacheManager檢索與 this 關聯的預設值CachingProvider。
- boolean isSupported(OptionalFeature feature) 檢查 this 是否支援指定的可選功能CachingProvider。
- void close() 關閉它CachingProvider並釋放與其關聯的所有資源。
- String getDefaultURI() 檢索 this 的預設 URI CachingProvider。
- Properties getDefaultProperties() 檢索用於配置此的預設屬性CachingProvider。
開發人員能夠管理快取提供程式、建立快取管理器以及在其應用程式中配置快取行為。它們提供了處理快取相關任務的靈活性,同時抽象了底層快取實現細節。
javax.cache.Caching
javax.cache.Caching是一個實用程式類,用作訪問 Java 應用程式中的快取功能的入口點。它提供靜態方法來建立和訪問快取提供程式和快取管理器。它抽象了獲取快取相關實體的過程,使開發人員更容易將快取功能整合到他們的應用程式中。
- CachingProvider getCachingProvider() 檢索預設快取提供程式。
- CacheManager getCacheManager() 檢索預設快取管理器。
- void closeCacheManager(CacheManager cacheManager) 關閉指定的快取管理器。
- Iterable<CachingProvider> getCachingProviders() 檢索所有已註冊快取提供程式的可迭代集合。
- Iterable<CacheManager> getCacheManagers(CachingProvider cachingProvider) 檢索與指定快取提供程式關聯的快取管理器的可迭代集合。
javax.cache.configuration
javax.cache.configuration包包含用於在 Java 應用程式中配置快取和快取管理器的類和介面。這些類和介面允許開發人員定義和自定義快取行為的各個方面,例如事件偵聽器、快取載入器/編寫器和統計資訊收集。一般來說,它提供了一種根據特定應用程式需求定義快取行為和設定的靈活方法。
- MutableConfiguration(Class<K> keyType, Class<V> valueType) MutableConfiguration使用指定的鍵和值型別構造一個新的。
- setStoreByValue(boolean isStoreByValue) 設定快取是否應按值或按引用儲存值。
- setTypes(Class<K> keyType, Class<V> valueType) 設定快取的鍵和值型別。
- setExpiryPolicyFactory(Factory<? extends ExpiryPolicy> factory) 設定為快取條目建立過期策略的工廠。
- setStatisticsEnabled(boolean isStatisticsEnabled) 設定是否啟用快取的統計資訊收集。
- setManagementEnabled(boolean isManagementEnabled) 設定是否為快取啟用管理(監控和配置)。
- addCacheEntryListenerConfiguration(CacheEntryListenerConfiguration<K, V> listenerConfiguration) 將快取條目偵聽器配置新增到快取。
- removeCacheEntryListenerConfiguration(CacheEntryListenerConfiguration<K, V> listenerConfiguration) 從快取中刪除快取條目偵聽器配置。
- setCacheWriterConfiguration(CacheWriterConfiguration<K, V> cacheWriterConfiguration) 設定快取的快取寫入器配置。
- setCacheLoaderConfiguration(CacheLoaderConfiguration<K, V> cacheLoaderConfiguration) 設定快取的快取載入器配置。
- setReadThrough(boolean isReadThrough) 設定如果在快取中未找到值,快取是否應讀取快取載入器。
- setWriteThrough(boolean isWriteThrough) 設定快取是否應寫入快取寫入器。
javax.cache.configuration.MutableConfiguration提供介面的可變實現Configuration。它允許開發人員在執行時修改快取設定,例如過期策略、大小限制、偵聽器和統計資訊收集。
javax.cache.expiry.ExpiryPolicy介面
javax.cache.expiry.ExpiryPolicy介面定義了快取條目的過期策略。它指定條目在被視為過期並可能從快取中逐出之前應在快取中保持有效的時間。ExpiryPolicy允許開發人員根據各種標準(例如建立時間、上次訪問時間或兩者的組合)指定不同的過期策略。預設情況下,a 中的條目javax.cache.Cache不會過期。
- AccessedExpiryPolicy 根據上次訪問時間使條目過期。當訪問某個條目時,其過期時間會從上次訪問開始延長固定的持續時間。
- CreatedExpiryPolicy 根據條目的建立時間使條目過期。條目在其建立時間的固定持續時間後過期。
- EternalExpiryPolicy 指示快取的條目永不過期。條目無限期地保留在快取中,直到顯式刪除為止。
- ModifiedExpiryPolicy 根據條目的修改時間使條目過期。當條目更新時,其過期時間會從上次更新後延長固定的持續時間。
監聽器和監聽器過濾器
在 Java 快取 API 中,偵聽器是用於監視與快取操作相關的事件並對其做出反應的機制。這些事件包括條目建立、更新、刪除和驅逐。JCache 提供兩種主要型別的監聽器:快取條目監聽器和快取管理器監聽器。此外,JCache 支援偵聽器過濾器,允許開發人員指定觸發偵聽器的條件。
快取條目偵聽器
當快取條目上發生特定事件時,例如建立、更新、刪除或逐出條目時,將呼叫快取條目偵聽器。這些偵聽器可以執行日誌記錄、觸發通知或根據快取事件更新外部系統等操作。
快取管理器監聽器
快取管理器偵聽器監視與快取管理器相關的事件,例如建立或關閉快取管理器的時間。它們提供了在快取管理器例項化或銷燬時執行初始化或清理任務的鉤子。
監聽器過濾器
偵聽器過濾器允許開發人員指定觸發偵聽器的條件。例如,過濾器可用於僅在滿足某些條件時呼叫偵聽器,例如當快取條目的值滿足特定條件或使用特定鍵更新條目時。
import javax.cache.event.*; |
在這個例子中:
- MyCacheEntryListener類實現CacheEntryCreatedListener監聽快取條目建立事件的介面。
- MyCacheListenerFilter類實現了CacheEntryEventFilter根據快取條目的值過濾事件的介面。
- CacheListenerExample類演示如何向過濾器註冊快取條目偵聽器並執行觸發偵聽器的快取操作。
下表列出了 Java 快取 API 中一些最流行的偵聽器介面類,以及它們的覆蓋方法和它們處理的事件型別。
- CacheEntryCreatedListener<K, V> onCreated 快取條目建立
- CacheEntryUpdatedListener<K, V> onUpdated 快取條目更新
- CacheEntryRemovedListener<K, V> onRemoved 快取條目刪除
- CacheEntryExpiredListener<K, V> onExpired 快取條目過期
- CacheEntryEvictedListener<K, V> onEvicted 快取條目驅逐
- CacheEntryReadListener<K, V> onRead 快取條目讀取(訪問)
- CacheEntryWriteListener<K, V> onWrite 快取條目寫入(放置或替換)
- CacheEntryListener<K, V> onCreated, onUpdated, onRemoved, onExpired,onEvicted 多種事件型別
- CacheManagerListener onManagerCreated,onManagerDestroyed 快取管理器建立/銷燬
Loader和Writer
快取載入器和快取寫入器是負責在快取缺失或更新時與外部資料來源互動的元件。它們允許開發人員將快取與底層資料儲存系統整合,實現快取資料與永續性資料來源之間的無縫同步。
快取載入器CacheLoader
快取載入器負責在快取中找不到請求資料(快取缺失)時,將外部資料來源的資料載入到快取中。它們提供一種機制,用來自資料庫或遠端服務等永續性儲存的資料填充快取,以確保快取中的請求資料可供後續訪問使用。快取閱讀器通常與直讀快取策略結合使用,在直讀快取策略中,快取被視為主資料儲存,缺失的快取條目會立即從整合的後端儲存中獲取。
- javax.cache.CacheLoader<K, V> load 將指定鍵的資料從外部源載入到快取中。
- loadAll 從外部源將多個鍵值對載入到快取中。
快取寫入器
另一方面,快取編寫器負責將對快取資料所做的更改傳播回外部資料來源。它們透過對快取資料所做的更改來更新持久儲存,從而確保快取與底層資料來源之間的一致性。快取寫入器通常與write-through快取策略結合使用,其中資料修改會立即反映在快取和外部資料儲存中。
- javax.cache.CacheWriter<K, V> write 將指定鍵值對的資料從快取寫入外部資料來源。
- delete 從外部資料來源刪除指定鍵的資料。
- writeAll 將多個鍵值對從快取寫入外部資料來源。
- deleteAll 從外部資料來源刪除多個鍵及其關聯值。
快取條目處理器EntryProcessor
由介面表示的快取記憶體條目處理器javax.cache.EntryProcessor是一種對快取記憶體條目執行原子操作的機制。它允許開發人員直接在快取節點(JVM)內執行自定義邏輯,提供了一種操作快取條目的方法,而無需外部資料來源、客戶端和快取節點之間的資料序列化/反序列化或複雜的同步機制。
快取條目處理器通常用於需要原子執行多個快取操作的場景,以確保一致性並避免競爭條件。當快取分佈在多個節點上(這種情況很常見)時,它們也特別有用。它們提供了一種在單個原子操作中封裝和執行快取條目上的自定義邏輯的方法,從而提高效能並降低資料不一致的風險。
下面介紹javax.cache.EntryProcessor基本方法。
- process 以原子方式對快取條目執行自定義邏輯,確保快取條目在處理過程中被鎖定。
- processAll 以原子方式對多個快取條目執行自定義邏輯,確保每個快取條目在處理過程中都被鎖定。
javax.cache.annotation
javax.cache.annotation包提供了註釋,開發人員可以使用註釋來標記用於快取目的的方法。這些註釋提供了一種控制快取行為的便捷方法,例如指定快取名稱、快取條目鍵和快取策略,而無需在方法實現中顯式快取邏輯。
- @CacheResult 標記一個方法,其返回值應該被快取。指定快取名稱和鍵,以及可選的快取解析程式。也適用於類,以影響該類的所有方法。
- @CachePut 標記其返回值應在快取中快取或更新的方法。指定快取名稱和鍵。也適用於類,以影響該類的所有方法。
- @CacheKey 顯式指定方法引數作為快取鍵。
- @CacheValue 使用時顯式指定一個方法引數作為快取值@CachePut
- @CacheRemove 標記從快取中刪除條目的方法。指定快取名稱和鍵。也適用於類,以影響該類的所有方法。
- @CacheRemoveAll 標記一個從快取中刪除所有條目的方法。指定快取名稱。也適用於類,以影響該類的所有方法。
- @CacheDefaults 指定類中方法的預設快取設定。可以定義預設快取名稱、鍵生成器等。僅適用於類。
import javax.cache.annotation.*; |
監控與管理
Java Caching API 在執行時提供管理和監視選項,以方便觀察和控制快取行為。這些選項使開發人員能夠監控快取使用情況、效能指標和配置詳細資訊,並動態管理快取生命週期和操作。
管理和監控選項
- JMX(Java 管理擴充套件):JCache 支援與 JMX 整合,允許快取實現將快取管理和監控功能公開為託管 bean。透過 JMX,開發人員可以透過程式設計方式或透過 JConsole 或 VisualVM 等管理工具訪問快取相關的屬性和操作。
- 指標和統計資訊:JCache 實現通常為收集和公開快取使用指標和統計資訊提供內建支援。這些指標可能包括命中/未命中率、快取大小、逐出計數和延遲測量,從而提供對快取效能和有效性的深入瞭解。
用於 JCache 管理的 JMX API
下面的表格列出了一些最常用的用於管理和監控 JCache 實現的 JMX API:
- javax.cache.management.CacheMXBean 透過 JMX 公開快取管理和監控功能,例如快取統計資訊、配置詳細資訊和操作。
- javax.cache.management.CacheStatisticsMXBean 透過 JMX 提供對快取統計資訊的訪問,例如命中/未命中計數、逐出計數和快取大小。
- javax.cache.management.CacheManagerMXBean 表示快取管理器的管理介面,透過 JMX 公開快取建立、銷燬和管理的方法。
- javax.cache.management.CacheManagerStatisticsMXBean 提供快取管理器統計資訊,例如透過 JMX 建立、銷燬和剩餘的快取數量。
- javax.cache.management.CacheMXBean.getCacheMXBeans() 檢索與快取管理器關聯的快取 MXBean 集合。
這些 JMX API 提供用於訪問快取和快取管理器管理和監控功能的標準化介面。透過與 JMX 整合,JCache 實現提供了一致且可互操作的方法來管理和監視執行時的快取操作。
供應商特定功能
它的unwrap方法允許開發人員獲取與特定 JCache 類或介面關聯的底層特定於實現的物件。當開發人員需要訪問標準 JCache API 未提供的特定於實現的特性或功能時,此方法非常有用。
- javax.cache.Cache 表示 JCache API 中的快取。允許儲存、檢索和管理快取的鍵值對。
- javax.cache.CacheManager 代表 JCache API 中的快取管理器。管理快取的生命週期並提供快取建立。
- javax.cache.Cache.Entry 代表快取中的一個條目。提供對與條目關聯的鍵、值和後設資料的訪問。
<font>// Unwrap Cache to Hazelcast ICache<i> |
請記住,如果您需要真正的快取提供程式可移植性,則不建議使用此功能,因為您的應用程式將耦合到特定於供應商的 API。
快取拓撲和模式
在快取系統的上下文中,快取拓撲是指分散式快取環境中快取的排列或結構。不同的快取拓撲在效能、可擴充套件性和一致性方面提供了不同的權衡。以下是一些常見的快取拓撲:
- 單節點快取:在此拓撲中,只有一個快取節點,通常執行在一臺伺服器或例項上。它是最簡單的快取形式,並提供基本的快取功能。然而,它缺乏可擴充套件性和容錯能力。
- 多個獨立快取:多個快取節點獨立執行,每個節點管理自己的快取。與單節點快取相比,這種拓撲具有更好的可擴充套件性,因為多個快取例項可以同時處理請求。然而,它缺乏跨快取的資料一致性。
- 複製快取:在複製快取拓撲中,整個資料集在所有快取節點上覆制。這確保每個快取節點都儲存資料的完整副本。它提供高可用性和容錯能力,因為任何節點故障都可以透過其他副本來緩解。但是,由於資料重複,可能會導致網路流量和記憶體消耗增加。
- 分割槽快取:在分割槽快取拓撲中,資料集基於一致的雜湊演算法跨多個快取節點進行分割槽。每個節點負責儲存和管理資料的子集。這允許水平可擴充套件性,因為資料集可以增長超出單個節點的容量。然而,管理跨分割槽的資料一致性和快取一致性可能具有挑戰性。
與快取拓撲類似,快取模式是指快取是客戶端應用程式的一部分還是作為單獨的服務執行。一般來說,以下模式在快取中很常見:
- 客戶端快取(嵌入式模式):在此模式下,快取在客戶端執行,通常在應用程式的 JVM 內。快取資料儲存在本地,減少了從遠端快取或伺服器獲取資料的需要。它可以透過減少網路延遲和伺服器負載來提高應用程式效能。但如果快取與伺服器端資料不同步,可能會導致資料不一致。
- 伺服器端快取(客戶端-伺服器模式):與客戶端快取相反,伺服器端快取將快取資料儲存在快取伺服器或節點內。它減輕了客戶端應用程式的快取責任,並集中了快取管理和協調。伺服器端快取可以更好地控制快取策略和資料一致性,但可能會為快取檢索操作引入額外的網路延遲。
每種快取拓撲和模式都有其優點和缺點,拓撲/模式組合的選擇取決於應用程式需求、可擴充套件性需求、容錯和資料一致性考慮等因素。組織通常採用快取拓撲和模式的組合來有效地滿足其特定的快取要求。
資源
以下資源提供了有關快取系統的豐富資訊,從基本概念到高階主題,為使用快取技術的開發人員、架構師和系統管理員提供了寶貴的參考。
- Oracle Java 快取 API 文件:
- 網站:Oracle 文件
- 描述:官方文件提供了有關 Java 快取 API (JCache) 的全面資訊,包括指南、教程和 API 參考。
- 網站:Ehcache 文件
- 描述:Ehcache 的文件提供了有關配置、部署和管理基於 Ehcache 的快取解決方案的深入資源,以及最佳實踐和故障排除指南。
- 網站:Apache Ignite 文件
- 描述:Apache Ignite 的文件提供了有關使用 Ignite 進行分散式快取、記憶體計算和資料處理的詳細指南和教程。
- 網站:Spring 快取文件
- 描述:Spring Framework 的快取文件提供了有關使用 Spring 的快取抽象以及與各種快取提供程式整合的指南,包括設定、配置和使用示例。