Redis缓存
框架对Redis进行了基础的调用封装,接口类为:org.go.framework.cache.CacheService,提供了众多方法可供使用。Dubbo服务端及Web端都可以直接引用该服务实例。
public void put(String key, Object value, int timeToLive, TimeUnit timeUnit, String namespace);
public void put(String key, Object value, int timeToIdle, int timeToLive, TimeUnit timeUnit, String namespace);
public boolean exists(String key, String namespace);
public Object get(String key, String namespace);
public Object get(String key, String namespace, int timeToIdle, TimeUnit timeUnit);
public void delete(String key, String namespace);
public void mput(Map map, int timeToLive, TimeUnit timeUnit, String namespace);
public Map mget(Collection keys, String namespace);
public void mdelete(Collection keys, String namespace);
public boolean containsKey(String key, String namespace);
public boolean putIfAbsent(String key, Object value, int timeToLive, TimeUnit timeUnit, String namespace);
public long increment(String key, long delta, int timeToLive, TimeUnit timeUnit, String namespace);
public boolean supportsTimeToIdle();
public boolean supportsUpdateTimeToLive();
public void invalidate(String namespace);
另外,还提供了一个缓存模板抽象类org.go.framework.cache.CacheService,可以快速实现缓存功能。
public abstract class AbstractBaseRedisCache extends AbstractDubboIntegrationService implements IDubboCache{
/**
* 设置缓存过期的分钟数
* @return
*/
protected abstract Integer getExpiredMinutes();
/**
* 缓存业务逻辑实现方法
* @param cacheKey
* @return
* @throws PendingException
*/
protected abstract V query(K cacheKey) throws PendingException;
/**
* 设置缓存查询失败的返回码
* @return
*/
protected abstract ResCode getErrResCode();
/**
* 指定缓存的命名空间
* @return
*/
protected abstract String getNameSpace();
/**
* 缓存的版本号,默认值为0
* 如果缓存的数据结构有变动,则需要修改版本号
* @return
*/
protected abstract int getVersion();
@Autowired
private CacheService cacheService;
/**
* 根据Key查询缓存对象
* @param key 缓存的Key
* @return
* @throws PendingException 需要进行处理
*/
@SuppressWarnings("unchecked")
public V get(K key) throws PendingException{
try {
//根据版本号调整后的命名空间
String adjustNameSpace = getNameSpace() + getVersion();
//从redis中查询缓存内容
CacheContainer result = (CacheContainer) cacheService.get(String.valueOf(key), adjustNameSpace);
if(result == null){
info("缓存不存在或已失效,需要重新查询信息。");
result = new CacheContainer(query(key));
cacheService.put(String.valueOf(key), result, getExpiredMinutes(), TimeUnit.MINUTES, adjustNameSpace);
}
return result.getObject();
} catch (Exception ex) {
error("缓存查询失败!", ex);
throw new PendingException(getErrResCode().getCode(), getErrResCode().getInfo());
}
}
/**
* 清除缓存
* @param key
* @throws PendingException
*/
public void clearCache(K key) throws PendingException{
try {
//根据版本号调整后的命名空间
String adjustNameSpace = getNameSpace() + getVersion();
//在redis中清除缓存信息
cacheService.delete(String.valueOf(key), adjustNameSpace);
}catch (Exception ex) {
error("缓存查询失败!", ex);
ResCode.REDIS_CACHE_DEL_ERR.throwException();
}
}
...
}
实现示例:
@Component
public class UserInfoRedisCache extends AbstractBaseRedisCache implements IUserInfoRedisCache {
@Reference(version = "1.0.0")
private UserInfoFacade userInfoFacade;
@Override
protected int getVersion() {
return 0; //版本号
}
@Override
protected String getNameSpace() {
return CacheNameSpaceConstants.User.USER_INFO_CACHE;
}
@Override
protected Integer getExpiredMinutes() {
return 60 * 24;// 一天
}
@Override
protected ResCode getErrResCode() {
return ResCode.userInfoCacheQueryFailed;
}
@Override
protected UserInfoItem query(Integer userId) throws PendingException {
// 查询用户信息
UserInfoRspDto userInfoResDto = getUserInfoById(userId);
// 转换返回结果
return BeanMapping.map(userInfoResDto, UserInfoItem.class);
}
/**
* 根据用户Id查询用户信息
*
* @param userId
* @return
* @throws PendingException
*/
private UserInfoRspDto getUserInfoById(Integer userId) throws PendingException {
// 组装查询条件
GetUserInfoReqDto getUserInfoReqDto = new GetUserInfoReqDto();
getUserInfoReqDto.setUserId(userId);
// 调用dubbo服务进行查询
UserInfoRspDto userInfoResDto = userInfoFacade.getUserInfo(getUserInfoReqDto);
// 如失败则抛出异常,用户查询没有空的概念
userInfoResDto.throwExceptionIfFailed();
return userInfoResDto;
}
}
本地缓存
本地缓存的模板抽象类是org.go.framework.cache.CacheService,实现机制原理与redis差不多,采用Guava的底层缓存框架实现。
本地缓存性能远高于Redis缓存,因此建议优先使用。但本地缓存因存放在各自虚拟机中,所以在多节点部署时需要考虑数据同步更新问题。