推薦鏈接:https://blog.csdn.net/sinat_32366329/article/details/80260944
JetCache
JetCache是由阿里巴巴開源的通用緩存訪問框架,相較於其他緩存框架該框架最大的特點就是將面向對象的思想應用到了緩存。
JetCache提供的核心能力包括:
提供統一的,類似jsr-107風格的API訪問Cache,並可通過註解創建並配置Cache實例
通過註解實現聲明式的方法緩存,支持TTL和兩級緩存
分佈式緩存自動刷新,分佈式鎖 (2.2+)
支持異步Cache API
Spring Boot支持
Key的生成策略和Value的序列化策略是可以定製的
針對所有Cache實例和方法緩存的自動統計
原文鏈接:https://blog.csdn.net/honger_hua/article/details/100009582
軟件要求
JDK1.8
Spring Framework 4.0.8及以上(可選,支持Annotation)
Spring Boot 1.1.9及以上(可選)
Boot項目配置
maven依賴
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.5.3</version>
</dependency>
解決衝突
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
MySpringBootApp.java
@SpringBootApplication
@EnableMethodCache(basePackages = "com.moguhu.oc")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp.class);
}
}
application.yml
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
limit: 100
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: ${redis.host}
port: ${redis.port}
方法緩存
我們可以使用@Cached用在接口方法上面。如下所示:
public interface UserService {
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
User getUserById(long userId);
}
expire表示返回值User對象,將在3600秒後過期,JetCache默認使用所有入參生成緩存的key。當然我們也可以手動指定key,如下所示:
public interface UserService {
@Cached(name="userCache-", key="#userId", expire = 3600)
User getUserById(long userId);
@CacheUpdate(name="userCache-", key="#user.userId", value="#user")
void updateUser(User user);
@CacheInvalidate(name="userCache-", key="#userId")
void deleteUser(long userId);
}
上面代碼中可以看出,我們可以使用SpEL(Spring Expression Language)來設置key和Value,當入參是對象時,可以使用對象中的一個字段,如 #user.userId 來設置。name屬性不是必須的,但是起個名字是個好習慣,展示統計數據的使用,會使用這個名字。如果同一個area兩個@CreateCache的name配置一樣,它們生成的Cache將指向同一個實例。這裏面需要注意的是,java代碼的編輯級別必須是1.8。
自動刷新
public interface SummaryService{
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
@CachePenetrationProtect
BigDecimal summaryOfToday(long catagoryId);
}
CachePenetrationProtect表示在多線程環境中同步加載數據。
緩存API
我們可以使用@CreateCache註解去創建一個Cache實例,默認超時時間是100秒:
@CreateCache(expire = 100, cacheType = CacheType.BOTH, localLimit = 50)
private Cache<Long, UserDO> userCache;
上面代碼創建了一個Cache實例。其中cacheType=CacheType.BOTH定義了一個2級緩存(本地和遠程),其中本地使用了LRU Cache,上線是50個,操作是可以看做是一個Map,如下所示:
UserDO user = userCache.get(12345L);
userCache.put(12345L, loadUserFromDataBase(12345L));
userCache.remove(12345L);
userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));
當然我們也可以手動的去創建Cache實例,如下:
GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
pc.setMinIdle(2);
pc.setMaxIdle(10);
pc.setMaxTotal(10);
JedisPool pool = new JedisPool(pc, "localhost", 6379);
Cache<Long, UserDO> userCache = RedisCacheBuilder.createRedisCacheBuilder()
.keyConvertor(FastjsonKeyConvertor.INSTANCE)
.valueEncoder(JavaValueEncoder.INSTANCE)
.valueDecoder(JavaValueDecoder.INSTANCE)
.jedisPool(pool)
.keyPrefix("userCache-")
.expireAfterWrite(200, TimeUnit.SECONDS)
.buildCache();
高級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
@CacheRefresh(timeUnit = TimeUnit.MINUTES, refresh = 60, stopRefreshAfterLastAccess = 100)
@CachePenetrationProtect
private Cache<String, Long> orderSumCache;
@PostConstruct
public void init(){
orderSumCache.config().setLoader(this::loadOrderSumFromDatabase);
}
傳統項目配置
如果沒有使用spring boot,可以按下面的方式配置(這裏使用jedis客戶端連接redis爲例)。
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-anno</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-redis</artifactId>
<version>2.5.4</version>
</dependency>
配置了這個JetCacheConfig類以後,可以使用@CreateCache和@Cached註解。
import java.util.HashMap;
import java.util.Map;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import com.alicp.jetcache.anno.support.GlobalCacheConfig;
import com.alicp.jetcache.anno.support.SpringConfigProvider;
import com.alicp.jetcache.embedded.EmbeddedCacheBuilder;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;
import com.alicp.jetcache.redis.RedisCacheBuilder;
import com.alicp.jetcache.support.FastjsonKeyConvertor;
import com.alicp.jetcache.support.JavaValueDecoder;
import com.alicp.jetcache.support.JavaValueEncoder;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.util.Pool;
@Configuration
@EnableMethodCache(basePackages = "com.company.mypackage")
@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, "localhost", 6379);
}
@Bean
public SpringConfigProvider springConfigProvider() {
return new SpringConfigProvider();
}
@Bean
public GlobalCacheConfig config(SpringConfigProvider configProvider, Pool<Jedis> pool){
Map localBuilders = new HashMap();
EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder
.createLinkedHashMapCacheBuilder()
.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.setConfigProvider(configProvider);
globalCacheConfig.setLocalCacheBuilders(localBuilders);
globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
globalCacheConfig.setStatIntervalMinutes(15);
globalCacheConfig.setAreaInCacheName(false);
return globalCacheConfig;
}
}