为什么需要缓存
- 降低数据库查询压力
- 提前准备好结果数据,从而提升服务器性能
- 幂等性判断
什么数据需要缓存
- 列表信息
- 变动不频繁列表,如: 员工列表
- 变动频繁的列表,如: 库存列表
- 单个信息通过主键缓存
- 加载产品信息
- 加载渠道信息
- 多服务器部署中,幂等性任务处理
- 订单处理中对订单进行缓存,并防止同时下单
环境准备工作
- 配置JetCache运行环境配置文件"tbd-redis.yml":
# 端口
#spring:
# redis:
# # redis服务器地址(默认为loaclhost)
# host: 192.168.0.206
# # redis端口(默认为6379)
# port: 6379
# # redis数据库索引(默认为0),避免和其他应用冲突,途比达序号为8,胖丁序号为6,数据中心序号为7
# database: 8
# # redis访问密码(默认为空)
# password: root,.123
# #超时连接
# timeout: 1000ms
# jedis:
# pool:
# #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
# max-wait: 1000ms
# #最大连接数据库连接数,设 0 为没有限制
# max-active: 100
# #最大等待连接中的数量,设 0 为没有限制
# max-idle: 8
# #最小等待连接中的数量,设 0 为没有限制
# min-idle: 0
remoteCache: &remoteCache
# type: redis
# keyConvertor: fastjson
# valueEncoder: kryo
# valueDecoder: kryo
# host: ${spring.redis.host:localhost}
# port: ${spring.redis.port:6379}
# password: ${spring.redis.password}
# database: ${spring.redis.database}
# poolConfig:
# minIdle: 5
# maxIdle: 20
# maxTotal: 50
type: redis.lettuce
keyConvertor: fastjson
valueEncoder: kryo
valueDecoder: kryo
# uri格式:redis://密码@ip:端口/redis库名?timeout=5s url[0]
# uri: redis://${spring.redis.password}@${spring.redis.password}:${spring.redis.port:6379}/7?timeout=5s
# redis数据库索引(默认为0),避免和其他应用冲突,途比达序号为8,胖丁序号为6,数据中心序号为7
# uri格式:redis://密码@ip:端口/redis库名?timeout=5s
uri: redis://root,.123@192.168.100.4:6379/8?timeout=1s
poolConfig:
minIdle: 0
maxIdle: 8
maxTotal: 100
localCache: &localCache
type: caffeine
keyConvertor: fastjson
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
# 默认1小时本地缓存
default:
<<: *localCache
expireAfterWriteInMillis: 60000
expireAfterAccessInMillis: 60000
# 長時本地緩存,主要用于要求时效一般
longTime:
<<: *localCache
expireAfterWriteInMillis: 300000
expireAfterAccessInMillis: 180000
# 短時本地緩存,主要用于要求时效较高的配置
shortTime:
<<: *localCache
expireAfterWriteInMillis: 3000
expireAfterAccessInMillis: 3000
remote:
# 默认1小时的远程缓存
default:
expireAfterWriteInMillis: 3600000
<<: *remoteCache
# 长时远程緩存,主要用于要求时效要求一般的集中式缓存
longTime:
expireAfterWriteInMillis: 7200000
<<: *remoteCache
# 短時远程緩存,主要用于要求时效较高的集中式缓存
shortTime:
expireAfterWriteInMillis: 300000
<<: *remoteCache
- pom.xml中引入jar包
<dependency>
<groupId>com.yanzuoguang</groupId>
<artifactId>yzg-util-redis</artifactId>
</dependency>
或者
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis-lettuce</artifactId>
</dependency>
- 项目中 "bootstrap.yml" 增加 引入配置文件"tbd-redis.yml "
spring:
cloud:
config:
name: tbd-redis
列表信息缓存
一般来说列表信息缓存信息都需要时效处理,这种缓存不需要删除,但是缓存时间不能太长(建议最长1-5分钟),但是需要定时失效.并通过整个对象转换为Json字符串后MD5,来确定是否自动重新刷新.
实现方式:
/**
* 查询分销渠道
*
* @param req
* @return
*/
@Cached(
// 默认规则名称:缓存时效规则,以及存储方式
area="shortTime",
// 缓存名称,通常定义到缓存常量中,防止缓存名称冲突
name = CacheName.SALE_SALE_QUERY,
// 缓存关键字,用于做唯一性判断,可以不配置,则由框架自动进行key值生成
key = "#req.toJsonMd5()",
// 结果为空时是否缓存
cacheNullValue = true,
// 同时缓存到redis,内存中(降低redis压力),可以分别配置redis缓存时间和
cacheType = CacheType.BOTH ,
// 本次配置时效单位.注意:配置文件中的值和这个单位无关.
timeUnit=TimeUnit.SECONDS,
// 本地内存缓存失效时间,可以单独配置,一般通过area属性来控制
localExpire = 3,
// Redis缓存失效时间,可以单独配置,一般通过area属性来控制
expire = 3
)
// 开启自动刷新
@CacheRefresh(
// 自动刷新时间
refresh = CacheName.REFRESH_TIME,
// 不访问后多长时间停止刷新
stopRefreshAfterLastAccess = CacheName.REFRESH_STOP
)
// 开启多线程缓存保护,即 @Cached.key 相等时则不缓存
@CachePenetrationProtect
PageSizeData<SaleSaleLoadResVo> query(SaleSaleQueryReqVo req);
单个信息缓存
一般来说单个信息缓存信息都可以保留较长时效,这种缓存需要在增加,修改时自动删除,缓存可以设置较长时间(建议最长30-60分钟),可以支持定时刷新,从而提升加载速度.并开启多线程保护.多个请求时,只一个人去加载.这个通过主键加载时不能通过扩展参数返回2种以上的不同结果.
实现方式:
/**
* 查询分销渠道
*
* @param req
* @return
*/
@Cached(
// 默认规则名称:缓存时效规则,以及存储方式,在配置文件中定义,默认为: default
area="default",
// 缓存名称,通常定义到缓存常量中,防止缓存名称冲突
name = CacheName.SALE_SALE,
// 缓存关键字,用于做唯一性判断,单个缓存中必须配置.
key = "#req.saleId",
// 结果为空时是否缓存
cacheNullValue = true,
// 同时缓存到redis,内存中(降低redis压力),可以分别配置redis缓存时间和
cacheType = CacheType.BOTH
)
// 开启自动刷新
@CacheRefresh(
// 自动刷新时间
refresh = CacheName.REFRESH_TIME,
// 不访问后多长时间停止刷新
stopRefreshAfterLastAccess = CacheName.REFRESH_STOP
)
// 开启多线程缓存保护,即 @Cached.key 相等时则不缓存
@CachePenetrationProtect
SaleSaleLoadResVo load(SaleSaleLoadReqVo req);
/**
* 分销渠道规则保存/修改
*
* @param req
* @return
*/
// 强制现有缓存失效
@CacheInvalidate(
// 默认规则名称:缓存时效规则,以及存储方式,在配置文件中定义,默认为: default
area="default",
// 缓存名称
name = CacheName.SALE_SALE,
// 缓存主键,得和 @Cached.key 相等
key = "#req.saleId"
)
String save(SaleSaleSaveReqVo req);
/**
* 删除分销信息
*
* @param req
* @return
*/
// 强制现有缓存失效
@CacheInvalidate(
// 默认规则名称:缓存时效规则,以及存储方式,在配置文件中定义,默认为: default
area="default",
// 缓存名称
name = CacheName.SALE_SALE,
// 缓存主键,得和 @Cached.key 相等
key = "#req.saleId"
)
int remove(SaleSaleRemoveReqVo req);
/**
* 渠道上下架
*
* @param req
* @return
*/
// 强制现有缓存失效
@CacheInvalidate(
// 默认规则名称:缓存时效规则,以及存储方式,在配置文件中定义,默认为: default
area="default",
// 缓存名称
name = CacheName.SALE_SALE,
// 缓存主键,得和 @Cached.key 相等
key = "#req.saleId"
)
String inline(SaleSaleInlineReqVo req);
多服务器部署中,幂等性任务处理
这种一般用于判断请求是否重复,并把一些重复的资源放入缓存中.从而提升最近一段时间该订单的加载速度.
@Compent
class Classs{
@CreateCache(name = "order:save:", expire = 3600, cacheType = CacheType.BOTH)
private Cache<String, OrderLoadResVo> cacheOrderSave;
// 生成分布式锁执行函数,同一个key同一时间只会有一个函数执行,100秒内每1秒钟检测一次
CacheLock.run(
// 缓存对象
cacheOrderSave,
// 等待最长时长
waitTime,
// 等待时间间隔
waitUnit,
// 等待关键字
key + "_RUN",
// 当key对应函数,没有其他人执行时,开始执行本函数.奇谈人执行则等待
new Runnable() {
@Override
public void run() {
// 读取缓存
OrderLoadResVo loadCache = cacheOrderSave.get(key);
// ....
// 写入缓存
cacheOrderSave.put(order.getOrderId(), load);
cacheOrderSave.put(channelKey, load);
}
});
}
本文由 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为: 2022/10/12 08:16