一、CaffeineCache排序
CaffeineCache是一個高性能的本地緩存工具,它作為一個新興的緩存框架,性能表現高於Guava Cache等前輩,其中緩存項的排序也是CaffeineCache比較顯著的特點,下面是一個簡單的使用代碼實例:
Cache cache = Caffeine.newBuilder().maximumSize(10)
.expireAfterWrite(5, TimeUnit.MINUTES)
.removalListener((key, value, cause) ->
log.info("key:{} value:{} 被移除,原因:{}", key, value, cause))
.build();
cache.put("a", 10);
cache.put("b", 20);
cache.put("c", 30);
Map map = cache.asMap();
List<Entry> entries = new ArrayList(map.entrySet());
entries.sort(Entry.comparingByValue());
這裡我們使用了Java的Map數據結構,通過將Map轉化成List,利用Java8的stream API進行排序。當然,CaffeineCache也可以自定義比較器實現排序。
二、CaffeineCache Spring Boot
當然,CaffeineCache也可以和Spring Boot集成,實現更便捷的使用方式,並可以利用Spring Boot提供的一些特性。具體的使用步驟如下:
1、首先在pom.xml中引入相關依賴:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、在Spring Boot項目的配置文件中配置CaffeineCache屬性:
spring.cache.type=caffeine spring.cache.caffeine.spec=maximumSize=100,expireAfterAccess=5s
3、在需要啟用CaffeineCache的Bean上添加@Cacheable註解即可:
@Cacheable(value="user-key")
public User getUserById(String userId) {
log.info("UserServiceImpl.getUserById() id: "+ userId);
return userDao.queryUserById(userId);
}
三、CaffeineCache使用
CaffeineCache的使用非常簡單,只需要按照下面的步驟操作即可:
1、我們需要創建一個CaffeineCache對象:
LoadingCache cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterAccess(1, TimeUnit.DAYS)
.build(new CacheLoader<String, String>() {
public String load(String key) throws Exception {
return createExpensiveGraph(key);
}
});
2、我們可以訪問緩存中的對象:
try {
String result = cache.get(key);
// Do something with result
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
3、我們也可以手動刷新緩存中的對象:
cache.refresh(key);
四、CaffeineCache源碼
CaffeineCache的源碼具有一定的複雜性,主要是由於其採用了CAS等技術實現了高性能以及線程安全等特性。下面是CaffeineCache的一個簡單單例模式實現代碼:
public class CaffeineCache {
private static Cache cache;
public static synchronized Cache getInstance() {
if (cache == null) {
cache = Caffeine.newBuilder()
.maximumSize(1000)
.build();
}
return cache;
}
}
五、CaffeineCacheLoad
CaffeineCache的加載機制也是其性能表現優異的原因之一,與Guava Cache類似,CaffeineCache也支持自定義加載機制,只需要實現CacheLoader接口即可:
LoadingCache graphs = Caffeine.newBuilder()
.maximumSize(10_000)
.build(key -> createExpensiveGraph(key));
private Graph createExpensiveGraph(Key key) {
return new Graph(key);
}
六、CaffeineCacheManager
CaffeineCache的管理器CaffeineCacheManager實現了Spring CacheManager的接口,可以與Spring Boot集成,由Spring Boot自動裝配。下面是CaffeineCacheManager的代碼示例:
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS));
return cacheManager;
}
七、CaffeineCache線程安全
CaffeineCache支持線程安全,通過重載CacheLoader和RemovalListener接口實現:
LoadingCache graphs = Caffeine.newBuilder()
.maximumSize(10_000)
.executor(Runnable::run) // DirectExecutor
.removalListener((key, graph, cause) -> {
if (cause.wasEvicted()) {
log.info("Graph with key {} was evicted ({})", key, cause.getCause());
}
})
.build(new CacheLoader() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
八、CaffeineCacheManager Redis
與Redis集成,需要引入以下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
然後在Spring Boot項目的配置文件中增加如下配置:
spring.cache.cache-names=cache_a,cache_b spring.cache.type=redis spring.redis.host=localhost spring.redis.password=password spring.redis.port=6379 spring.redis.database=1 spring.cache.redis.use-key-prefix=true spring.cache.redis.key-prefix=my_app_prefix spring.cache.redis.cache-null-values=true
最後,我們可以創建RedisCache對象並設置CaffeineCache為其CacheLoader:
CacheLoader<Object, Object> myCacheLoader = new CacheLoader<Object, Object>() {
public Object load(Object key) {
// do something to load cache
...
}
};
RedisCache myCache = new RedisCache("cacheName", lettuceConnectionFactory, myCacheConfig);
LoadingCache<Object, Object> cache = Caffeine.newBuilder().maximumSize(10000).build(myCacheLoader);
myCache.setCaffeineCache(cache);
九、CaffeineCache本地調試不生效
如果我們在本地調試時,發現CaffeineCache不生效,可以嘗試以下方式進行解決:
1、確認是否注入了CaffeineCacheManager,以及是否配置了有效的屬性。
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS));
return cacheManager;
}
2、確認是否在啟動類中添加@EnableCaching註解。
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3、如果使用了Spring Boot,可以在application.yml或者application.properties中增加如下代碼:
management:
endpoints:
web:
exposure:
include: "*"
以上就是對CaffeineCache的詳細介紹,我們可以根據不同的需求,選擇不同的使用方式以及相關配置,並可以利用其提供的高性能、線程安全等特性,優化我們的應用程序性能。
原創文章,作者:XTMJA,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/317023.html
微信掃一掃
支付寶掃一掃