J2Cache + SpringBoot的应用
项目中之前用的是redis缓存,但是在循环查询时,redis偶尔也会出现连接超时的问题,说明redis虽然是内存中处理,速度比较快,但是还是会有开销。尤其是对于高频次请求时,也会有瓶颈。
1,引入maven依赖
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-spring-boot2-starter</artifactId>
<version>2.8.0-release</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.8.2-release</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
2,yml配置文件配置J2Cache相关属性
spring:
# 接入redis
redis:
database: 11
host: ##
port: ##
password: ##
#客户端超时时间单位是毫秒 默认是2000
timeout: 5000
#最大空闲数
maxIdle: 20
#连接池的最大数据库连接数
maxActive: -1
#控制一个pool可分配多少个jedis实例,用来替换上面的maxActive
maxTotal: 100
#最大建立连接等待时间。如果超过此时间将接到异常
maxWaitMillis: 100
#连接的最小空闲时间
minEvictableIdleTimeMillis: 864000000
#每次释放连接的最大数目
numTestsPerEvictionRun: 10
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程
timeBetweenEvictionRunsMillis: 300000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
testOnBorrow: true
#在空闲时检查有效性
testWhileIdle: false
j2cache:
open-spring-cache: true
cache-clean-mode: passive
allow-null-values: true
redis-client: lettuce #指定redis客户端使用lettuce,也可以使用Jedis
l2-cache-open: true #开启二级缓存,false则表示只使用一级缓存
# 事件通知的机制,j2cache从1.3.0版本开始支持JGroups和Redis Pub/Sub两种方式进行缓存事件的通知。
# 此处我们使用基于redis的发布订阅模式来通知缓存的各个节点来进行缓存数据的同步(由j2cache进行实现,我们写上配置即可)
broadcast: net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
# broadcast: jgroups
L1: #指定一级缓存提供者为caffeine
provider_class: caffeine
L2: #指定二级缓存提供者为redis
provider_class: net.oschina.j2cache.cache.support.redis.SpringRedisProvider
config_section: lettuce
sync_ttl_to_redis: true
default_cache_null_object: false
serialization: fst
caffeine:
properties: /caffeine.properties
# lettuce是redis的一个客户端,也可以使用jedis,都是用来操作redis的java客户端
lettuce:
mode: single
namespace:
storage: generic
channel: j2cache
scheme: redis
hosts: ${spring.redis.host}:${spring.redis.port}
password: ${spring.redis.password}
database: ${spring.redis.database}
sentinelMasterId:
maxTotal: 100
maxIdle: 10
minIdle: 10
timeout: 10000
caffeine.properties
#########################################
# Caffeine configuration
# [name] = size, xxxx[s|m|h|d]
#########################################
# 默认区域,最多可以放入5000个缓存对象,缓存时间,s表示秒,m分钟,h小时,d天
default = 5000, 1d
# 定义的第二个缓存的区域
adrm.account = 5000, 2d
# 定义的第三个缓存的区域
adrm.dept = 1000, 4d
# 定义的第四个缓存的区域
adrm.person = 2000, 7d
对于缓存区域,可根据业务需求(缓存数量、过期时间不一样)自定义多个。区域名称随便自定义,当缓存区域名称能够在caffeine.properties中匹配上时,该缓存区域的过期时间,最大缓存对象就会用配置上的参数。如果匹配不上,则默认用default 区域的配置参数。
3,J2Cache 用法
@Resource
private CacheChannel cacheChannel;
@Override
public String getAgentShortNameByCache(Long id){
Object agent = null;
try {
// 该区域配置中没有设置,默认default的配置,超时时间1d
agent = cacheChannel.get("adrm.agent", id.toString()).getValue();
} catch (Exception e) {
log.error("缓存获取代理商异常:", e);
}
if (null != agent) {
return JSON.parseObject(agent.toString(), AgentPo.class).getAgentShortName();
}
AgentPo po = agentRepository.getById(id);
if (null != po) {
cacheChannel.set("adrm.agent", id.toString(), JSON.toJSONString(po));
return po.getAgentShortName();
}
return "";
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(AgentPo agent) {
boolean bool = agentRepository.updateById(agent);
if (bool) {
cacheChannel.evict(AdRedisKeyConstant.AGENT, agent.getId().toString());
}
return bool;
}
/**
* 根据工号查询用户名称
* @param crmId
* @return
*/
public UserPo getByCrmId(String crmId) {
if (StringUtils.isBlank(crmId)) {
return null;
}
Object user = null;
try {
user = cacheChannel.get("adrm.person", crmId).getValue();
} catch (Exception e) {
log.error("缓存中根据人员crmId获取人员异常:", e);
}
if (null != user) {
return JSON.parseObject(user.toString(), UserPo.class);
}
UserPo userPo = userRepository.lambdaQuery().eq(UserPo::getCrmId, crmId).one();
if (ObjectUtil.isEmpty(userPo)) {
return null;
}
// 该区域配置中有adrm.person的配置,超时时间7d
cacheChannel.set("adrm.person", crmId, JSON.toJSONString(userPo));
return userPo;
}
代码未贴出全部,报错请修改。