特性
全部特性:
- 通過統一的API訪問Cache系統
- 通過註解實現聲明式的方法緩存,支持TTL和兩級緩存
- 通過註解創建並配置
Cache
實例 - 針對所有
Cache
實例和方法緩存的自動統計 - Key的生成策略和Value的序列化策略是可以配置的
- 分佈式緩存自動刷新,分佈式鎖 (2.2+)
- 異步Cache API (2.2+,使用Redis的lettuce客戶端時)
- Spring Boot支持
JetCache整合srpingboot配置
maven配置
<!--注意版本要對應,不然會報錯-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.0</version>
</dependency>
<!--可能要加-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
application.yml配置
jetcache:
statIntervalMinutes: 1
areaInCacheName: false
local:
default:
type: caffeine
limit: 100
keyConvertor: fastjson
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: 47.98.129.125
port: 6379
#password:***
#sentinels: 127.0.0.1:26379 , 127.0.0.1:26380, 127.0.0.1:26381
#masterName: mymaster
使用JavaConfig配置(與application.yml配置二選一)
@Configuration
@EnableMethodCache(basePackages = "com.example.demo.cache")
@EnableCreateCacheAnnotation
public class JetCacheConfig {
@Bean
public Pool<Jedis> pool() {
GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
pc.setMinIdle(2);
pc.setMaxIdle(10);
pc.setMaxTotal(10);
return new JedisPool(pc, "47.98.129.125", 6379);
}
@Bean
public ConfigProvider configProvider() {
return new ConfigProvider();
}
@Bean
public GlobalCacheConfig config( Pool<Jedis> pool) {
Map localBuilders = new HashMap();
EmbeddedCacheBuilder localBuilder = CaffeineCacheBuilder
.createCaffeineCacheBuilder()
.limit(100)
.keyConvertor(FastjsonKeyConvertor.INSTANCE);
localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);
Map remoteBuilders = new HashMap();
RedisCacheBuilder remoteCacheBuilder = RedisCacheBuilder.createRedisCacheBuilder()
.keyConvertor(FastjsonKeyConvertor.INSTANCE)
.valueEncoder(JavaValueEncoder.INSTANCE)
.valueDecoder(JavaValueDecoder.INSTANCE)
.jedisPool(pool);
remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder);
GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
globalCacheConfig.setLocalCacheBuilders(localBuilders);
globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
globalCacheConfig.setStatIntervalMinutes(15);
globalCacheConfig.setAreaInCacheName(false);
return globalCacheConfig;
}
}
常用註解
啓動類上加註解,開啓緩存:
@EnableMethodCache(proxyTargetClass = true,basePackages = "com.shinemo.migu.activity.thirdapi.core")
@EnableCreateCacheAnnotation
方法上的註解
獲取時:
@Cached(name = "award.getById", key = "#id", cacheType = CacheType.LOCAL, expire = 300)
修改時:
@CacheUpdate(name="userCache-", key="#user.userId", value="#user")
void updateUser(UserDO user);
刪除時:
@CacheInvalidate(name = "userService2.getUserById", key = "#id")
代碼示例:
@Service
public class UserService2 {
@Autowired
private UserDao userDao;
@Cached(name = "userService2.getUserById", key = "#id", cacheType = CacheType.BOTH, expire = 60*5)
@CacheRefresh(refresh = 10, stopRefreshAfterLastAccess = 60)
public UserDO getUserById(Integer id) {
UserDO userDO = userDao.selectById(id);
return userDO;
}
public void addUser(UserDO user) {
userDao.insert(user);
}
@CacheUpdate(name = "userService2.getUserById", key = "#user.id",value = "#user" )
public void updateUser(UserDO user) {
userDao.updateById(user);
}
@CacheInvalidate(name = "userService2.getUserById", key = "#id")
public void deleteUser(Integer id) {
//userDao.deleteById(id);
}
}
實例變量上的註解
創建緩存實例:
@CreateCache(cacheType = CacheType.LOCAL, name = "jobActivityCache", timeUnit = TimeUnit.MINUTES, expire = 5)
private Cache<Integer,UserDO> userCache;
@CreateCache(name = "UserService.userCache", expire = 100, cacheType = CacheType.BOTH, localLimit = 50)
private Cache<Long, UserDO> userCache;
代碼示例:
@Service
public class UserService {
@CreateCache(name = "UserService.userCache", cacheType = CacheType.REMOTE, localLimit = 50,expire = 60*5)
private Cache<Integer, UserDO> userCache;
@Autowired
private UserDao userDao;
public UserDO getUserById(Integer id) {
UserDO userDO = userCache.get(id);
if (userDO == null) {
UserDO userDB = userDao.selectById(id);
if (userDB == null) {
throw new RuntimeException("數據不存在");
}
userCache.put(id, userDB);
return userDB;
}
return userDO;
}
public void addUser(UserDO user) {
userDao.insert(user);
}
public void updateUser(UserDO user) {
userDao.updateById(user);
userCache.put(user.getId(), user);
}
public void deleteUser(Integer id) {
//userDao.deleteById(id);
userCache.remove(id);
}
}
刷新緩存
@CacheRefresh
刷新緩存,可以加在方法上,也可以加在實例上:
@CacheRefresh(refresh = 60, stopRefreshAfterLastAccess = 300) //60秒刷新一次,如果300秒內沒有訪問,則停止刷新
cacheType爲REMOTE或者BOTH的時候,刷新行爲是全局唯一的,也就是說,即使應用服務器是一個集羣,也不會出現多個服務器同時去刷新一個key的情況。
一個key的刷新任務,自該key首次被訪問後初始化,如果該key長時間不被訪問,在stopRefreshAfterLastAccess指定的時間後,相關的刷新任務就會被自動移除,這樣就避免了浪費資源去進行沒有意義的刷新。
@CachePenetrationProtect
@CachePenetrationProtect表示在多線程環境中同步加載數據。
高級API
異步API
CacheGetResult r = cache.GET(userId);
CompletionStage<ResultData> future = r.future();
future.thenRun(() -> {
if(r.isSuccess()){
System.out.println(r.getValue());
}
});
分佈式鎖
cache.tryLockAndRun("key", 60, TimeUnit.SECONDS, () -> heavyDatabaseOperation());
設置讀取器並自動刷新
@CreateCache(name = "UserService3.userCache",timeUnit = TimeUnit.SECONDS,expire = 1000,cacheType = CacheType.BOTH)
@CacheRefresh(timeUnit = TimeUnit.SECONDS, refresh = 30, stopRefreshAfterLastAccess = 600)
@CachePenetrationProtect
private Cache<String, List<UserDO>> userCache;
@PostConstruct
public void init(){
userCache.config().setLoader(this::loadUser);
}
public List<UserDO> loadUser(String key) {
List<UserDO> userDOS = userDao.selectList(null);
return userDOS;
}