SpringBoot
/SpringCloud
构建微服务所需分布式缓存
和分布式锁
的一种实现。
maven repo
: (还未上传)mvn install
或 加入自己的工程;# 以application.yml为例
gallop:
cache:
# 设置默认的缓存策略执行器。支持nop/redis/memory,配置不存在时使用nop
executor-strategy: redis
# 默认的延迟双删时间间隔(毫秒)。配置不存在时使用默认值2000
delay-removal-millis: 5000
# 缓存策略需要redis连接
spring:
redis:
host: 127.0.0.1
port: 6379
password: foobar
// 查询+加载
import com.gallop.common.cache.CacheQuery;
import com.gallop.common.cache.CacheQueryConstants;
import com.gallop.common.cache.CacheQueryKey;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class FooBarServiceImpl implements FooService {
// 其他代码略...
@CacheQuery(
primaryKey = "TEST_CACHE_PRIMARY_KEY",
expireAfter = 10,
expireTimeUnit = TimeUnit.SECONDS,
cacheStrategy = CacheQueryConstants.ExecutorStrategy.REDIS
)
public FooBean queryFooByProp(@CacheQueryKey String prop1) {
return xxxx;
}
}
上述代码定义了一个会使用缓存的查询方法queryFooByProp
,如果方法以如下方式调用:
fooBarService.queryFooByProp("abcd");
此时,缓存检查会代替方法本身被优先触发。同时注意到缓存策略为REDIS
,程序会使用键:
"TEST_CACHE_PRIMARY_KEY:abcd"
来查询redis,如果找到了未过期的缓存值,此方法调用会直接返回;否则执行方法本身,返回值以同样的键加入缓存,并设置10秒
的有效期。
// 缓存设置失效
import com.gallop.common.cache.CacheExecutor;
import com.gallop.common.cache.CacheQueryConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FooBarServiceImpl implements FooService {
// 其他代码略...
@Autowired
private CacheExecutor cacheExecutor;
public Boolean removeFoo(FooBean fooBean) {
// 数据本身的删除
removeById(fooBean.getId());
// 删除缓存
cacheExecutor.removeCache("TEST_CACHE_PRIMARY_KEY", fooBean.getProp1());
// 另: 删除缓存,并使用默认时间间隔延迟再次执行一次删除操作
cacheExecutor.removeCacheWithDelay("TEST_CACHE_PRIMARY_KEY", fooBean.getProp1());
}
}
上述代码中给出了删除缓存的示例(CacheExecutor
提供了针对缓存的插入,查询,删除等全部操作,并提供多种重载,实际上@CacheQuery
注解只是调用这些方法的其中一种方式)。
CacheExecutor
可直接注入bean中,默认对应配置gallop.cache.executor-strategy
设置的执行器。
如果想使用其他自定义执行器,可直接注入相关执行器引用。当前支持的缓存策略执行器有:
执行器 | 对应枚举 | 引用示例 |
---|---|---|
NopCacheExecutor(缺省无操作实现) | CacheQueryConstants.ExecutorStrategy.NOP | @Autowired private NopCacheExecutor executor; |
InMemoryCacheExecutor(单机场景实现) | CacheQueryConstants.ExecutorStrategy.MEMORY | @Autowired private InMemoryCacheExecutor executor; |
RedissonCacheExecutor(分布式场景主要实现) | CacheQueryConstants.ExecutorStrategy.REDIS | @Autowired private RedissonCacheExecutor executor; |
配置文件决定的默认执行器(未配置时为NOP) | CacheQueryConstants.ExecutorStrategy.DEFAULT | @Autowired private CacheExecutor executor; |
queryFooByProp
会使用缓存框架,按照查询缓存-> 加载并缓存的逻辑执行。
当缓存命中时,不会调用方法本身(缓存直接返回);否则执行方法并把返回结果加入缓存;主键
+参数列表
拼接构成,主键
在@CacheQuery
中定义,
参数列表
在方法参数列表中通过@CacheQueryKey
声明,可声明0个或多个(needParam
控制)。@CacheQuery
暂不支持加在接口方法上!spring aop
的触发机制,同一类中this.xxx(foo,bar)
方式调用缓存修饰方法会导致注解失效。
请确保@CacheQuery
注解修饰的方法能够被正确触发。
(临时方案:注入自身引用并使用@Lazy修饰,通过注入的引用调用自己;后续考虑使用动态代理解决此问题)CacheQuery
:参数 | 说明 | 备注 |
---|---|---|
primaryKey | 保存缓存所使用的的主键 | 自定义的字符串常量; primaryKey 和 value 二者选一,优先使用primaryKey |
value | 保存缓存所使用的的主键(内置枚举类型) | CacheQueryConstants.PrimaryKey 枚举变量 ; primaryKey 和 value 二者选一,优先使用primaryKey |
expireAfter | 缓存有效期 | |
expireTimeUnit | 缓存有效期时间单位 | 默认秒 |
cacheStrategy | 缓存执行器选择(内存/redis/无) | 默认使用配置gallop.cache.executor-strategy 指定的类型,未指定时使用NOP |
cacheNullValue | 是否缓存null 值 |
默认false |
needParam | 缓存key是否拼接方法参数(参数列表中@CacheQueryKey修饰的参数) | 默认true 。 主键和参数列表一起参与缓存key的构造, 如果为true 时方法参数中没有发现CacheQueryKey 修饰的参数,缓存将会失效 |
assembleHandler | 主键和参数列表的拼接方式 | 默认格式为 主键:参数1:参数2:... ,可通过实现接口的bean自行定义 |
updateOption | 缓存更新策略 | 默认不触发。PREDICATE 模式下,即使缓存命中还要判断一次是否查询新值替换缓存。 |
updatePredicate | 缓存更新策略执行器Class,需要是一个spring-bean,只在updateOption=PREDICATE模式下有效 | 在注解中提供bean的class或在方法列表中以参数形式提供bean,两种方式均可 |
CacheQueryKey
:使用场景: 参与缓存key拼接的方法参数使用此注解。加在@CacheQuery
修饰的方法参数上;
拼接方式: 使用默认的参数拼接器时,所有参数会通过toString
方法转字符串,并通过:
连接;
最后和主键
连接在一起。例: FOO_BAR_PK:arg1:arg2
;当@CacheQuery#needParam
设置false
时,
只使用主键
作为缓存key,忽略参数;
支持类型: 理论上支持所有的参数类型,但其中几种特殊情况如下:
类型 | 转换方法 |
---|---|
枚举类 | 使用name() 转字符串 |
AssembleKeyParameter接口 | 使用toKey() 转字符串,支持更多的自定义参数转换场景 |
CacheExecutor
:说明:
api:
CacheKeyAssembleHandler
:说明:
默认实现:
自定义:
UpdateOption
和 CacheUpdatePredicate
:使用场景:
自定义:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。