現代應用開發中,性能和可擴展性是決定係統成敗的關鍵因素。緩存通過減少數據庫負載、降低延遲和確保無縫用戶體驗,在提升這些方面發揮著關鍵作用。然而,沒有一種單一的緩存解決方案能夠完美適應所有場景。
本地緩存(例如 Caffeine)由於在內存中運行並靠近應用程序,因此能夠提供極快的速度。它們非常適合減少頻繁訪問數據的響應時間。另一方面,分佈式緩存(例如使用 Redis 的 Redisson)在應用程序的多個實例之間提供可擴展性和一致性。分佈式緩存確保分佈式系統中的所有節點訪問相同最新的數據,這在多節點環境中至關重要。
然而,僅僅依賴本地或分佈式緩存都會帶來挑戰:
這就是 混合緩存成為有效解決方案的地方。通過結合使用Caffeine 和Redisson 的本地和分佈式緩存的優勢,您可以獲得本地緩存速度帶來的高性能,同時利用分佈式緩存保持一致性和可擴展性。
本文探討如何在 Spring Boot 應用程序中實現混合緩存,以確保最佳性能和數據一致性。
首先,將必要的依賴項添加到您的 pom.xml
文件中:
<code class="language-xml"><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.43.0</version> </dependency></code>
以下是緩存配置:
<code class="language-java">@Configuration @EnableCaching public class CacheConfig implements CachingConfigurer { @Value("${cache.server.address}") private String cacheAddress; @Value("${cache.server.password}") private String cachePassword; @Value("${cache.server.expirationTime:60}") private Long cacheExpirationTime; @Bean(destroyMethod = "shutdown") RedissonClient redisson() { Config config = new Config(); config.useSingleServer().setAddress(cacheAddress).setPassword(cachePassword.trim()); config.setLazyInitialization(true); return Redisson.create(config); } @Bean @Override public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(cacheExpirationTime, TimeUnit.MINUTES)); return cacheManager; } @Bean public CacheEntryRemovedListener cacheEntryRemovedListener() { return new CacheEntryRemovedListener(cacheManager()); } @Bean @Override public CacheResolver cacheResolver() { return new LocalCacheResolver(cacheManager(), redisson(), cacheEntryRemovedListener()); } }</code>
CacheManager
負責管理緩存的生命週期,並提供對適當緩存實現(例如本地或分佈式)的訪問。在本例中,我們使用 CaffeineCacheManager
來啟用內存緩存,並通過 Caffeine
配置過期策略。
CacheResolver
動態地確定要對特定操作使用哪個緩存。在這裡,LocalCacheResolver
連接本地(Caffeine)和分佈式(Redisson)緩存,確保有效應用混合策略。
<code class="language-java">@Component public class LocalCacheResolver implements CacheResolver { // ... (代码与原文相同) ... }</code>
<code class="language-java">public class LocalCache implements Cache { // ... (代码与原文相同) ... }</code>
CacheEntryRemovedListener
監聽從分佈式緩存(Redis)中移除的條目,並確保它們也從各個節點的本地緩存中移除,從而保持一致性。
<code class="language-xml"><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.43.0</version> </dependency></code>
執行用 @Cacheable
註解的方法時,會呼叫 put
方法。這會將資料儲存在本機快取 (Caffeine) 和分散式快取 (Redis) 中:
<code class="language-java">@Configuration @EnableCaching public class CacheConfig implements CachingConfigurer { @Value("${cache.server.address}") private String cacheAddress; @Value("${cache.server.password}") private String cachePassword; @Value("${cache.server.expirationTime:60}") private Long cacheExpirationTime; @Bean(destroyMethod = "shutdown") RedissonClient redisson() { Config config = new Config(); config.useSingleServer().setAddress(cacheAddress).setPassword(cachePassword.trim()); config.setLazyInitialization(true); return Redisson.create(config); } @Bean @Override public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(cacheExpirationTime, TimeUnit.MINUTES)); return cacheManager; } @Bean public CacheEntryRemovedListener cacheEntryRemovedListener() { return new CacheEntryRemovedListener(cacheManager()); } @Bean @Override public CacheResolver cacheResolver() { return new LocalCacheResolver(cacheManager(), redisson(), cacheEntryRemovedListener()); } }</code>
要檢索數據,系統會先檢查本地快取中是否存在該鍵。如果找不到該鍵,則查詢分散式快取。如果分散式快取中存在該值,則將其新增至本機快取中,以便更快地進行後續存取:
<code class="language-java">@Component public class LocalCacheResolver implements CacheResolver { // ... (代码与原文相同) ... }</code>
當發生快取驅逐時(例如,透過 @CacheEvict
註解),該鍵將從分散式快取中移除。其他節點的本地快取將透過 CacheEntryRemovedListener
收到通知,以移除相同的鍵:
<code class="language-java">public class LocalCache implements Cache { // ... (代码与原文相同) ... }</code>
混合快取結合了本地記憶體快取的速度和分散式快取的可擴展性和一致性。這種方法解決了僅使用本地或分散式快取的限制。透過在 Spring Boot 應用程式中整合 Caffeine 和 Redisson,您可以實現顯著的效能改進,同時確保應用程式節點之間的資料一致性。
使用 CacheEntryRemovedListener
和 CacheResolver
可確保快取條目在所有快取層之間保持同步,為現代可擴充應用程式提供高效且可靠的快取策略。這種混合方法在分散式系統中尤其寶貴,因為在這些系統中,效能和一致性都至關重要。
以上是春季啟動中的混合緩存策略:Redisson和咖啡因整合的指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!