Java 緩存中介軟體
關鍵詞:Spring Cache、J2Cache、JetCache一 、JSR 107
JSR107 中制訂了 Java 緩存的規範。
因此,在很多緩存框架、緩存庫中,其 API 都參考了 JSR 107 規範。
Java Caching 定義了 5 個核心介面
CacheManager
。一個套用可以在執行期存取多個
CachingProvider
。
二、Spring Cache
詳見: Spring Cache 官方文件Spring 作為 Java 開發最著名的框架,也提供了緩存功能的框架—— Spring Cache。
Spring 支持基於註釋(annotation)的緩存(cache)技術,它本質上不是一個具體的緩存實作方案(例如:EHCache 或 OSCache),而是一個對緩存使用的抽象,透過在既有程式碼中添加少量它定義的各種 annotation,即能夠達到緩存方法的返回物件的效果。
Spring Cache 的特點:
開啟緩存註解
Spring 為緩存功能提供了註解功能,但是你必須啟動註解。
有兩種方式:
(一)使用標記註解
@EnableCaching
這種方式對於 Spring 或 Spring Boot 專案都適用。
@Configuration
@EnableCaching
public class AppConfig {
}
(二)在 xml 中聲明
<cache:annotation-driven cache-manager="cacheManager"/>
spring 緩存註解 API
Spring 對緩存的支持類似於對事務的支持。
首先使用註解標記方法,相當於定義了切點,然後使用 Aop 技術在這個方法的呼叫前、呼叫後獲取方法的入參和返回值,進而實作了緩存的邏輯。
@Cacheable
@Cacheable
用於觸發緩存
。
表明所修飾的方法是可以緩存的:當第一次呼叫這個方法時,它的結果會被緩存下來,在緩存的有效時間內,以後存取這個方法都直接返回緩存結果,不再執行方法中的程式碼段。
這個註解可以用
condition
內容來設定條件,如果不滿足條件,就不使用緩存能力,直接執行方法。
可以使用
key
內容來指定 key 的生成規則。
@CachePut
@CachePut
用於更新緩存
。
與
@Cacheable
不同,
@CachePut
不僅會緩存方法的結果,還會執行方法的程式碼段。
它支持的內容和用法都與
@Cacheable
一致。
@CacheEvict
@CacheEvict
用於清除緩存
。
與
@Cacheable
功能相反,
@CacheEvict
表明所修飾的方法是用來刪除失效或無用的緩存數據。
下面是
@Cacheable
、
@CacheEvict
和
@CachePut
基本使用方法的一個集中展示:
@Service
public class UserService {
// @Cacheable可以設定多個緩存,形式如:@Cacheable({"books", "isbns"})
@Cacheable(value={"users"}, key="#user.id")
public User findUser(User user) {
return findUserInDB(user.getId());
}
@Cacheable(value = "users", condition = "#user.getId() <= 2")
public User findUserInLimit(User user) {
return findUserInDB(user.getId());
}
@CachePut(value = "users", key = "#user.getId()")
public void updateUser(User user) {
updateUserInDB(user);
}
@CacheEvict(value = "users")
public void removeUser(User user) {
removeUserInDB(user.getId());
}
@CacheEvict(value = "users", allEntries = true)
public void clear() {
removeAllInDB();
}
}
@Caching
@Caching
用於組合定義多種緩存功能
。
如果需要使用同一個緩存註解(
@Cacheable
、
@CacheEvict
或
@CachePut
)多次修飾一個方法,就需要用到
@Caching
。
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)
@CacheConfig
@CacheConfig
用於定義公共緩存配置
。
與前面的緩存註解不同,這是一個類級別的註解。
如果類的所有操作都是緩存操作,你可以使用
@CacheConfig
來指定類,省去一些配置。
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
三、Spring Boot Cache
詳見: Spring Boot Cache 特性官方文件Spring Boot Cache 是在 Spring Cache 的基礎上做了封裝,使得使用更為便捷。
Spring Boot Cache 快速入門
(1)引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- 按序引入需要的緩存庫 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2)緩存配置
例如,選用緩存為 redis,則需要配置 redis 相關的配置項(如:資料來源、連線池等配置資訊)
# 緩存類別,支持類別:GENERIC、JCACHE、EHCACHE、HAZELCAST、INFINISPAN、COUCHBASE、REDIS、CAFFEINE、SIMPLE
spring.cache.type = redis
# 全域緩存時間
spring.cache.redis.time-to-live = 60s
# Redis 配置
spring.redis.database = 0
spring.redis.host = localhost
spring.redis.port = 6379
spring.redis.password =
(3)使用
@EnableCaching
開啟緩存
@EnableCaching
@SpringBootApplication
public class Application {
// ...
}
(4)緩存註解(
@Cacheable
、
@CachePut
、
@CacheEvit
等)使用方式與 Spring Cache 完全一樣
四、JetCache
JetCache 是一個基於 Java 的緩存系統封裝,提供統一的 API 和註解來簡化緩存的使用。 JetCache 提供了比 SpringCache 更加強大的註解,可以原生的支持 TTL、兩級緩存、分布式自動重新整理,還提供了
Cache
介面用於手工緩存操作。 當前有四個實作,
RedisCache
、
TairCache
(此部份未在 github 開源)、
CaffeineCache
(in memory)和一個簡易的
LinkedHashMapCache
(in memory),要添加新的實作也是非常簡單的。
詳見: jetcache Github
jetcache 快速入門
如果使用 Spring Boot,可以按如下的方式配置(這裏使用了 jedis 客戶端連線 redis,如果需要集群、讀寫分離、異步等特性支持請使用 lettuce 客戶端)。
(1)引入 POM
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.5.14</version>
</dependency>
(2)配置
配置一個 spring boot 風格的 application.yml 檔,把他放到資源目錄中
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: 127.0.0.1
port: 6379
(3)開啟緩存
然後建立一個 App 類放在業務包的根下,EnableMethodCache,EnableCreateCacheAnnotation 這兩個註解分別啟用 Cached 和 CreateCache 註解,其他和標準的 Spring Boot 程式是一樣的。這個類可以直接 main 方法執行。
package com.company.mypackage;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp. class);
}
}
(4)API 基本使用
建立緩存例項
透過 @CreateCache 註解建立一個緩存例項,預設超時時間是 100 秒
@CreateCache(expire = 100)
private Cache<Long, UserDO> userCache;
用起來就像 map 一樣
UserDO user = userCache.get(123L);
userCache.put(123L, user);
userCache.remove(123L);
建立一個兩級(記憶體+遠端)的緩存,記憶體中的元素個數限制在 50 個。
@CreateCache(name = "UserService.userCache", expire = 100, cacheType = CacheType.BOTH, localLimit = 50)
private Cache<Long, UserDO> userCache;
name 內容不是必須的,但是起個名字是個好習慣,展示統計數據的使用,會使用這個名字。如果同一個 area 兩個 @CreateCache 的 name 配置一樣,它們生成的 Cache 將指向同一個例項。
建立方法緩存
使用 @Cached 方法可以為一個方法添加上緩存。JetCache 透過 Spring AOP 生成代理,來支持緩存功能。註解可以加在介面方法上也可以加在類方法上,但需要保證是個 Spring bean。
public interface UserService {
@Cached(name="UserService.getUserById", expire = 3600)
User getUserById(long userId);
}
五、j2cache
六、總結
使用緩存框架,使得開發緩存功能非常便捷。
如果你的系統只需要使用一種緩存,那麽推薦使用 Spring Boot Cache。Spring Boot Cache 在 Spring Cache 基礎上做了封裝,使用更簡單、方便。
如果你的系統需要使用多級緩存,那麽推薦使用 jetcache。
參考資料