内容简介:7.0.4 版本修改日志: 1. 修复了Magic模式下数据不正确问题; 2. 支持无参函数下使用Magic模式; 3. 对Magic模式下的缓存删除功能进行重构,不仅支持基于参数进行批量删除缓存,也支持通过返回进行批量删除缓存;...
7.0.4 版本修改日志:
1. 修复了Magic模式下数据不正确问题;
2. 支持无参函数下使用Magic模式;
3. 对Magic模式下的缓存删除功能进行重构,不仅支持基于参数进行批量删除缓存,也支持通过返回进行批量删除缓存;
下面是对Magic模式的详细说明:
为了降低缓存数据与数据源数据不一致,也是为了更加方便更新、删除缓存,通常做法是,数据以主键为key进行缓存,然后根据id获取数据,如下面两段代码所示:
public interface UserMapper {
/**
* 根据用户id获取用户信息
*
* @param id
* @return
*/
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60", key = "'user-byid-' + #args[0]")
UserDO getUserById(Long id);
/**
* 根据动态组合查询条件,获取用户id列表
*
* @param condition
* @return
**/
List<Long> listIdsByCondition(UserCondition condition);
}
下面是根据一定的查询用户信息:
public List<UserDO> listByCondition(UserCondition condition) {
List<Long> ids = userMapper.listIdsByCondition(condition);
List<UserDO> list = null;
if (null != ids && ids.size() > 0) {
list = new ArrayList<>(ids.size());
UserDO userDO = null;
for (Long id : ids) {
userDO = userMapper.getUserById(id);
if (null != userDO) {
list.add(userDO);
}
}
}
return list;
}
如果上面ids有10条记录,最差的情况需要访问10次缓存和10数据源,以及写10次缓存才能完成以上操作,最好的情况也需要访问10次缓存才能完成操作。 使用Magic模式,则会将参数分隔,先批量去缓存中查询,获取命中的缓存,然后将缓存未命中的,再批量从数据源加载,然后把从数据源加载的数据刷入缓存,最后把缓存命中的与数据源加载的数据一并返回。 下面是使用Magic模式进行优化:
public interface UserMapper {
/**
* 根据用户id获取用户信息
*
* @param id
* @return
*/
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60", key = "'user-byid-' + #args[0]")
UserDO getUserById(Long id);
/**
* 根据动态组合查询条件,获取用户id列表
*
* @param condition
* @return
**/
List<Long> listIdsByCondition(UserCondition condition);
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60",
key = "'user-byid-' + #args[0]",
magic = @Magic(key = "'user-byid-' + #retVal.id", iterableArgIndex = 0))
List<UserDO> listByIds(@Param("ids") List<Long> ids);
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60",
// 因为Magic 模式下会对参数进行分隔,所以取参数固定使用 #args[0],
// 如果参数据是复杂类型,比如List<UserDO>, 那么取参使用 #args[0].id
// 为了降低缓存不致问题,些处生的有key值要与getUserById 方法的一样
key = "'user-byid-' + #args[0]",
magic = @Magic(
// 因为Magic 模式下会对数组及集合类型的数据进行分隔,所以取返回值固定使用 #retVal,
// 此key表达生成的值也必须要与getUserById 方法的一样
key = "'user-byid-' + #retVal.id", iterableArgIndex = 0))
List<UserDO> listByIds(@Param("ids") List<Long> ids);
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60",
// 因为Magic 模式下会对参数进行分隔,所以取参数固定使用 #args[0],
// 如果参数据是复杂类型,比如List<UserDO>, 那么取参使用 #args[0].id
// 为了降低缓存不致问题,些处生的有key值要与getUserById 方法的一样
key = "'user-byid-' + #args[0]",
magic = @Magic(
// 因为Magic 模式下会对数组及集合类型的数据进行分隔,所以取返回值固定使用 #retVal,
// 此key表达生成的值也必须要与getUserById 方法的一样
key = "'user-byid-' + #retVal.id", iterableArgIndex = 0))
List<UserDO> listByIds2(@Param("ids") Long... ids);
}
下面是在没有使用Magic模式下根据一定条件查询用户信息,先获取用户id列表,然后再遍历获取用户详细信息:
public List<UserDO> listByCondition(UserCondition condition) {
List<Long> ids = userMapper.listIdsByCondition(condition);
List<UserDO> list = null;
if (null != ids && !ids.isEmpty()) {
list = userMapper.listByIds(ids);
}
return list;
}
使用Magic模式后,如果上面ids有10条记录,最差情况需要访问1次缓存、1数据源以及1次写缓存操作;最好的情况只需要访问1次缓存。但使用Magic模式后,就不允许使用自动加载(autoload设置为true也不会生效)、不支持“拿来主义”、异步刷新等功能。
@Cache(expire = 60, expireExpression = "null == #retVal ? 30: 60",
key = "", magic = @Magic(key = "'user-magic-'+ #retVal.id"))
public List<UserDO> loadUsers() {
List<UserDO> list = new ArrayList<>(5);
for (Long id = 100L; id < 105; id++) {
list.add(new UserDO(id, "name" + id, "ppp"));
}
return list;
}
有时我们也需要动态精确批量删除缓存,比如更新一批商品信息后,也要批量删除缓存,在7.0.1版本之前需要在业务代码中使用循环操作来实现。 7.0.4版本中增加@CacheDeleteMagicKey 用于开启Magic模式,并支持对参数或返回值进行分割,然后生成多个Cache key进行批量删除缓存。如下例子所示:
/**
* 根据用户ids删除用户记录
**/
@CacheDelete(magic = { @CacheDeleteMagicKey(value = "'user-byid-' + #args[0]", condition = "#retVal > 0", iterableArgIndex = 0, iterableReturnValue = false) })
int deleteUserByIds(@Param("ids") Long... ids);
// 遍历ids,删除所有缓存, iterableReturnValue 必须设置false
@CacheDelete(magic = {
@CacheDeleteMagicKey(value = "'user-testMagic-' + #args[0] + '-' + #args[1] + '-' + #args[2]", iterableArgIndex = 2, iterableReturnValue = false)
})
public void testDeleteMagicForArg(String name, String password, Long... ids) {
}
// 遍历返回值,删除所有缓存,iterableArgIndex必须设置为-1, iterableReturnValue 必须设置为true
@CacheDelete(magic = {
@CacheDeleteMagicKey(value = "'user-testMagic-' + #args[0] + '-' + #args[1] + '-' + #retVal.id", iterableArgIndex = -1, iterableReturnValue = true)
})
public List<UserDO> testDeleteMagicForRetVal(String name, String password, Long... ids) {
List<UserDO> list = new ArrayList<>(ids.length);
for (Long id : ids) {
list.add(new UserDO(id, name, password));
}
return list;
}
使用Magic模式不仅能简少手动遍历的代码,同时也会使用 redis 的Pipeline批量处理,减少与Redis的交互次数,提升性能。
以上所述就是小编给大家介绍的《AutoLoadCache 7.0.4 发布,完善 Magic 模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 自己动手修改完善yilia主题
- 自己动手修改完善yilia主题(下)
- React入门-井字游戏实现与完善
- 更完善的 Docker + Traefik 使用方案
- 让Docker日臻完善的8个优秀工具
- 禅道 11.1 版本发布,主要完善细节,修复 bug
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。