摘要: JetCache是由阿里巴巴開源的通用緩存訪問框架,若是你對Spring Cache很熟悉的話,請必定花一點時間瞭解一下JetCache,它更好用。JetCache能夠作相似Spring Cache的註解式緩存,支持TTL、多級緩存、分佈式自動刷新,也提供相似JSR107規範的Cache API。git
JetCache是由阿里巴巴開源的通用緩存訪問框架,若是你對Spring Cache很熟悉的話,請必定花一點時間瞭解一下JetCache,它更好用。github
JetCache提供的核心能力包括:json
咱們直接看代碼,最簡單的使用場景是這樣的:緩存
public interface UserService { @Cached(expire = 3600, cacheType = CacheType.REMOTE) User getUserById(long userId); }
這和Spring Cache很像,不過@Cached註解原生支持了TTL(超時時間),cacheType有LOCAL/REMOTE/BOTH三種選擇,
分別表明本地內存/遠程Cache Server(例如Redis)/兩級緩存,可根據狀況選用,合理的使用LOCAL或BOTH類型能夠下降Cache Server的壓力以及咱們提供的服務的響應時間。服務器
再看個複雜點的例子:框架
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); }
第一個例子中咱們沒有指定key,JetCache會根據參數自動生成,這個例子咱們指定了key,而且展現了緩存的更新和刪除。異步
自動刷新是JetCache的大殺器:分佈式
public interface SummaryService{ @Cached(expire = 3600, cacheType = CacheType.REMOTE) @CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS) BigDecimal salesVolumeSummary(int timeId, long catagoryId); }
cacheType爲REMOTE或者BOTH的時候,刷新行爲是全局惟一的,也就是說,即便應用服務器是一個集羣,也不會出現多個服務器同時去刷新一個key的狀況。
一個key的刷新任務,自該key首次被訪問後初始化,若是該key長時間不被訪問,在stopRefreshAfterLastAccess指定的時間後,相關的刷新任務就會被自動移除,這樣就避免了浪費資源去進行沒有意義的刷新。ui
加在方法上的註解畢竟不能提供最靈活的控制,因此JetCache提供了Cache API,使用起來就像Map同樣:this
UserDO user = userCache.get(12345L); userCache.put(12345L, loadUserFromDataBase(12345L)); userCache.remove(12345L); userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));
實際上Cache API實現了jsr107規範Cache接口的部分方法,之後的大版本可能會完整實現。
Cache實例能夠經過註解建立:
@CreateCache(expire = 100, cacheType = CacheType.BOTH, localLimit = 50) private Cache<Long, UserDO> userCache;
也能夠經過和guava cache/caffeine相似的builder來建立:
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();
Cache接口支持異步:
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());
使用Cache API也能夠作自動刷新哦:
@CreateCache @CacheRefresh(timeUnit = TimeUnit.MINUTES, refresh = 60) private Cache<String, Long> orderSumCache; @PostConstruct public void init(){ orderSumCache.config().setLoader(this::loadOrderSumFromDatabase); }
若是沒有使用註解,用builder同樣也能夠作出自動刷新:
Cache<String, Long> orderSumCache = RedisCacheBuilder.createRedisCacheBuilder() ......省略 .refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS)) .loader(this::loadOrderSumFromDatabase) .buildCache();
當前支持的緩存系統包括如下4個,並且要支持一種新的緩存也是很是容易的:
使用JetCache的系統需求:
更多文檔能夠在github的wiki上找到。