Caffeine
Caffeine是一种基于Java的高性能缓存库,它提供了可配置、快速、灵活的缓存实现。Caffeine具有以下特点:
- 高性能:Caffeine使用了一些优化技术,如基于链表的并发哈希表和无锁算法,以提供卓越的读写性能。
- 容量控制:Caffeine支持多种容量控制策略,如基于大小、基于权重和基于时间等,可以根据需求设置缓存的最大大小或最大权重,并在缓存达到限制时进行逐出策略。
- 过期策略:Caffeine提供了各种内置的过期策略,如基于访问时间、基于写入时间和定时过期等,在缓存中存储的对象可以根据这些策略进行自动过期。
- 异步加载:Caffeine支持异步加载数据,当缓存中不存在某个键对应的值时,可以通过自定义的Loader接口来异步加载数据。
- 统计和监听:Caffeine提供了缓存统计功能,可以获取缓存的命中率、缓存项数量等信息,还支持注册缓存监听器,在缓存发生变化时触发相应的事件。
序列化
Caffeine缓存不涉及任何序列化,因此目标缓存对象不需要实现Serializable
接口。若涉及多级缓存或者多种缓存共用,其它需要网络传输或者持久化的缓存需要序列化,Caffeine尽管也使用实现序列化的实体类,但是不做序列化操作。
不需要序列化,降低了缓存使用难度。
引入依赖
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
全局配置
spring:
cache:
type: caffeine
缓存配置
配置缓存管理器:多CacheName配置。
public interface CacheNameTimeConstant {
String CACHE_DEFAULT = "CACHE_DEFAULT";
String CACHE_10SECS = "CACHE_10SECS";
String CACHE_60SECS = "CACHE_60SECS";
}
同一个CacheManager配置多个CacheName,此处仅配置过期时间的差异,其余配置可自由增加。
import com.example.demo.util.CacheNameTimeConstant;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Configuration
public class CaffeineConfig{
@Bean
public CacheManager caffeineCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<>();
caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_5SECS,
Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build()));
caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_10SECS,
Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build()));
caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_30SECS,
Caffeine.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build()));
cacheManager.setCaches(caches);
return cacheManager;
}
}
controller
@RestController
@RequestMapping("/test")
public class TestController {
@Resource
private StuMapper stuMapper;
/**
* 添加缓存
*/
@GetMapping("/selectStu/{id}")
@Cacheable(value = CacheNameTimeConstant.CACHE_30SECS,key="#id")
public Student selectStu(@PathVariable Integer id){
return stuMapper.selectById(id);
}
/**
* 更新缓存
*/
@PostMapping("/updateStu")
@CachePut(value = CacheNameTimeConstant.CACHE_30SECS,key = "#student.id")
public Student updateStu(Student student){
if (stuMapper.updateById(student) > 0) {
return stuMapper.selectById(student.getId());
}
return null;
}
/**
* 删除缓存
*/
@PostMapping("/deleteStu/{id}")
@CacheEvict(value = CacheNameTimeConstant.CACHE_30SECS,key = "#id")
public String deleteStu(@PathVariable Integer id){
return stuMapper.deleteById(id) > 0 ? "删除成功" : "删除失败";
}
}
启动类
添加@EnableCaching注解
@SpringBootApplication
@EnableTransactionManagement
@EnableCaching
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
System.out.println("启动成功");
}
@Bean
public MessageConverter jsonMessageConverter(){
return new Jackson2JsonMessageConverter();
}
}
测试
第一次查询,是走数据库的
第二次查询不走数据库,直接返回缓存,但是30s后过期
更新缓存
再次查询数据时,从更新的缓存获取