Введение в универсальный кэш-доступный фреймворк JetCache, открытый Alibaba
JetCache — это универсальный кэш-доступный фреймворк, открытый компанией Alibaba. Если вы знакомы с Spring Cache, обязательно потратите немного времени, чтобы ознакомиться с JetCache, он более удобен в использовании.
Основные возможности, предоставляемые JetCache, включают:
public interface UserService {
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
User getUserById(long userId);
}
Это похоже на Spring Cache, но аннотация @Cached
нативно поддерживает TTL (время жизни), а параметр cacheType
имеет три варианта: LOCAL, REMOTE и BOTH, которые соответственно означают локальный кэш в памяти, удаленный сервер кэша (например, Redis) и двухуровневое кэширование. Выбор зависит от конкретной ситуации, и правильное использование LOCAL или BOTH типов может снизить нагрузку на сервер кэша и ускорить время отклика предоставляемых вами услуг.Рассмотрим более сложный пример:
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);
}
В первом примере мы не указываем ключ, и JetCache генерирует его автоматически на основе параметров. В этом примере мы явно указываем ключ и демонстрируем обновление и удаление кэша. Автоматическая перезагрузка и защита от проникновения являются мощными инструментами JetCache, особенно для объектов с высокой стоимостью загрузки, чтобы предотвратить высокую конкуренцию при пропуске кэша и перегрузку базы данных:
public interface SummaryService{
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
@CachePenetrationProtect
BigDecimal salesVolumeSummary(int timeId, long catagoryId);
}
Когда cacheType
равен REMOTE или BOTH, поведение перезагрузки является глобально уникальным, то есть даже если сервер приложений является кластером, не будет ситуации, когда несколько серверов одновременно перезагружают один и тот же ключ.
Аннотация CachePenetrationProtect
гарантирует, что когда кэш пропускает запрос, в одном JVM только один поток будет выполнять метод, а остальные потоки будут ждать результат.
Задача перезагрузки ключа инициализируется после первого доступа к ключу. Если ключ долго не используется, задача перезагрузки будет автоматически удалена через время, указанное в stopRefreshAfterLastAccess
, что позволяет избежать траты ресурсов на бесполезную перезагрузку.Аннотации, добавленные к методам, в конечном итоге не могут обеспечить самую гибкую форму контроля, поэтому JetCache предоставляет API кэша, который используется аналогично Map:```java
UserDO user = userCache.get(12345L);
userCache.put(12345L, loadUserFromDataBase(12345L));
userCache.remove(12345L);
userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));
Инстансы кэша могут быть созданы через CacheManager (в версии 2.7 аннотация CreateCache была отменена), и в случае одинакового area и name, они используют один и тот же инстанс кэша, как и аннотация @Cached:
```java
@Autowired
private CacheManager cacheManager;
private Cache<String, UserDO> userCache;
@PostConstruct
public void init() {
QuickConfig qc = QuickConfig.newBuilder("userCache")
.expire(Duration.ofSeconds(100))
.cacheType(CacheType.BOTH) // two level cache
.syncLocal(true) // invalidate local cache in all jvm processes after update
.build();
userCache = cacheManager.getOrCreateCache(qc);
}
Также можно создать инстансы кэша с помощью билдера, аналогичного guava cache/caffeine (это низкоуровневый API):
GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
pc.setMinIdle(2);
pc.setMaxIdle(10);
pc.setMaxTotal(10);
JedisPool pool = new JedisPool(pc, "127.0.0.1", 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 кэша поддерживает асинхронные операции:
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());
```Использование инстансов кэша также позволяет настроить автоматическое обновление:
```java
@PostConstruct
public void init() {
QuickConfig qc = QuickConfig.newBuilder("userCache")
.refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS))
.build();
userCache = cacheManager.getOrCreateCache(qc);
}
Низкоуровневый API также позволяет создать автоматическое обновление:
Cache<String, Long> orderSumCache = RedisCacheBuilder.createRedisCacheBuilder()
......省略
.refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS))
.loader(this::loadOrderSumFromDatabase)
.buildCache();
Поддерживаемые системы кэширования включают следующие 4, и добавление новой системы кэширования также является простым процессом:
Требования к системе для использования JetCache:
Дополнительная документация доступна в разделе docs репозитория на Github.
С помощью JetCache нам становится легче использовать единый интерфейс для доступа к кэшу.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )