自命为缓存之王的Caffeine

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自命为缓存之王的Caffeine相关的知识,希望对你有一定的参考价值。

您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~




说了很多Caffeine的基本特性,但是骡子是马,终归还是要看能不能拉磨。SpringBoot有两种使用Caffeine的方式:

1、直接引入Caffeine依赖,然后使用Caffeine方法实现缓存;

2、引入Caffeine和Spring Cache依赖,使用注解方式实现缓存。

先实现第一种方式(之前已实现过,整合到SpringBoot),这种方式比较灵活。再使用第二种方式(用注解实现Caffeine缓存功能),这种方式比较方便。

先引入依赖:

<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>

在配置文件中加入(这是可选的):

## CAFFEINE
customer.caffeine.initialCapacity=50
customer.caffeine.maximumSize=500
customer.caffeine.expireAfterWrite=86400

声明注入代码:

/**
* 声明注入代码
*
* @author 湘王
*/
@Configuration
@Component
public class WebConfiguration extends WebMvcConfigurationSupport
/**
* 进程外缓存初始化
*
*/
@Bean("cache")
public LoadingCache<String, String> cache()
return Caffeine.newBuilder()
.initialCapacity(1024)
.maximumSize(1024)
.expireAfterWrite(1, TimeUnit.HOURS)
.build(key ->
return "";
);

然后在代码中调用:

/**
* 功能描述
*
* @author 湘王
*/
public class CaffeineTest
@Resource
private LoadingCache<String, String> cache;

/**
* 保存缓存数据
*
*/
public void setCache(final String key, final String value)
cache.put(key, value);


/**
* 读取缓存数据
*
*/
public String getCache(final String key)
return cache.get(key);


/**
* 清除缓存数据
*
*/
public void clearCache(final String key)
cache.invalidate(key);


然后再来看看第二种方式。先引入依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>

在属性文件中加入配置:

## CAFFEINE
spring.cache.cache-names=test
spring.cache.type=caffeine
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=300s

定义一个实体类(之前用过的类):

/**
* 用户entity
*
* @author 湘王
*/
public class SysUser implements Serializable, RowMapper<SysUser>
private static final long serialVersionUID = -1214743110268373599L;

private int id;
private int bid;
private String username;
private String password;
private int scope; // 0:全部,1:部门及以下,2:仅个人
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
protected Date createtime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
protected Date updatetime;

public int getId()
return id;


public void setId(int id)
this.id = id;


public int getBid()
return bid;


public void setBid(int bid)
this.bid = bid;


public String getUsername()
return username;


public void setUsername(String username)
this.username = username;


@JsonIgnore
public String getPassword()
return password;


public void setPassword(String password)
this.password = password;


public int getScope()
return scope;


public void setScope(int scope)
this.scope = scope;


public Date getCreatetime()
return createtime;


public void setCreatetime(Date createtime)
this.createtime = createtime;


public Date getUpdatetime()
return updatetime;


public void setUpdatetime(Date updatetime)
this.updatetime = updatetime;


@Override
public SysUser mapRow(ResultSet result, int i) throws SQLException
SysUser user = new SysUser();

user.setId(result.getInt("id"));
user.setUsername(result.getString("username"));
user.setPassword(result.getString("password"));
user.setCreatetime(result.getTimestamp("createtime"));
user.setUpdatetime(result.getTimestamp("updatetime"));

return user;


然后定义服务类:

/**
* 缓存服务
*
* @author 湘王
*/
@Service
public class CaffeineService
/**
* 将新增的用户信息放入缓存
*
*/
@CachePut(value = "test", key = "#id")
public int addUser(int id, String username, String password)
String sql = "";
// TODO SOMETHING
return -1;


/**
* 从缓存读取用户信息,id作为key
*
*/
@Cacheable(value = "test", key = "#id")
public SysUser queryById(int id)
System.out.println("从数据库读取:" + id);
String sql = "";
// TODO SOMETHING
return new SysUser();


/**
* 从缓存读取用户信息,username作为key
*
*/
@Cacheable(value = "test", key = "#username")
public SysUser queryByUsername(String username)
System.out.println("从数据库读取:" + username);
String sql = "";
// TODO SOMETHING
return new SysUser();

再定义Contorller类:

/**
* 缓存COntroller
*
* @author 湘王
*/
@RestController
public class CacheController
@Resource
private CaffeineService caffeineService;

/**
* 添加用户
*
*/
@PostMapping("/user/add")
public String add(int id, String username, String password)
caffeineService.addUser(id, username, password);
return "添加用户成功";


/**
* 查询用户
*
*/
@GetMapping("/user/id")
public String id(int id)
SysUser user = caffeineService.queryById(id);
return "查询到用户:" + user.getUsername();


/**
* 查询用户
*
*/
@GetMapping("/user/username")
public String username(String username)
SysUser user = caffeineService.queryByUsername(username);
return "查询到用户:" + user.getUsername();


先添加用户,再分别通过ID和用户名查询,可以看到:

1、第一次查询,会从数据库中读取;

2、第二次查询,就直接从Caffeine中读取了。

当超过设定的300s后,再次读取又会从数据中查询。

使用注解的方式简单、快速,但注解缺点是不能灵活操控,如异步存储和无法查看统计信息。



感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

以上是关于自命为缓存之王的Caffeine的主要内容,如果未能解决你的问题,请参考以下文章

自命为缓存之王的Caffeine

缓存之王Caffeine Cache,性能比Guava更强,命中率更高!

本地缓存之王——Caffeine 组件最强讲解!

SpringBoot 集成缓存性能之王 Caffeine

万字详解本地缓存之王 Caffeine 的高性能设计之道!

本地缓存性能之王Caffeine