阿里巴巴開源的通用緩存訪問框架JetCache介紹

JetCache是由阿里巴巴開源的通用緩存訪問框架,若是你對Spring Cache很熟悉的話,請必定花一點時間瞭解一下JetCache,它更好用。git

JetCache提供的核心能力包括:github

  • 提供統一的,相似jsr-107風格的API訪問Cache,並可經過註解建立並配置Cache實例
  • 經過註解實現聲明式的方法緩存,支持TTL和兩級緩存
  • 分佈式緩存自動刷新,分佈式鎖 (2.2+)
  • 支持異步Cache API
  • Spring Boot支持
  • Key的生成策略和Value的序列化策略是能夠定製的
  • 針對全部Cache實例和方法緩存的自動統計

咱們直接看代碼,最簡單的使用場景是這樣的: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指定的時間後,相關的刷新任務就會被自動移除,這樣就避免了浪費資源去進行沒有意義的刷新。分佈式

加在方法上的註解畢竟不能提供最靈活的控制,因此JetCache提供了Cache API,使用起來就像Map同樣:ui

UserDO user = userCache.get(12345L);
userCache.put(12345L, loadUserFromDataBase(12345L));
userCache.remove(12345L);

userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));

實際上Cache API實現了jsr107規範Cache接口的部分方法,之後的大版本可能會完整實現。this

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個,並且要支持一種新的緩存也是很是容易的:

  • Caffeine(基於本地內存)
  • LinkedHashMap(基於本地內存,JetCache本身實現的簡易LRU緩存)
  • Alibaba Tair(相關實現未在Github開源,在阿里內部Gitlab上能夠找到)
  • Redis

使用JetCache的系統需求:

  • JDK:必須Java 8
  • Spring Framework:4.0.8以上,若是不使用註解就不須要
  • Spring Boot:1.1.9以上(可選)

更多文檔能夠在github的wiki上找到。

有了JetCache,咱們就能夠更方便的基於統一的接口訪問緩存。

詳情請閱讀原文

相關文章
相關標籤/搜索