一、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/n/317023.html