问题代码
线上出现的问题写法,本文通过伪代码例子代码说明,来看一个常规的获取例子代码:
public Object getOrderInfo(int orderId, String cacheKey){
Object orderInfo = getCache(cacheKey);
if (null != orderInfo) {
return orderInfo;
}
orderInfo = getDb(orderId);
if(null != orderInfo){
setCache(cacheKey, orderInfo);
}
return orderInfo;
}
public Object getCache(String cacheKey){
try{
Object orderInfo = new Object();
return orderInfo;
}catch (Exception e){
logger.error("getCache error", e);
}
return null;
}
public boolean setCache(String cacheKey, Object orderInfo) {
redisClient.set(cacheKey, orderInfo);
return true;
}
public Object getDb(int orderId){
return new Object();
}
问题1 : 缓存不能影响业务逻辑
setCache如果有异常,那么直接往上层抛异常,直接导致业务获取失败了
所以需要立刻改正
public boolean setCache(String cacheKey, Object orderInfo) {
try {
redisClient.set(cacheKey, orderInfo);
return true;
} catch (Throwable e) {
logger.error("setCche error:{}", cacheKey, e);
}
return false;
}
问题2 : 缓存需要过期
另外需要检查自己的过期策略配置是否正确
public boolean setCache(String cacheKey, Object orderInfo) {
try {
long expireTime = 60;
redisClient.set(cacheKey, orderInfo, expireTime);
return true;
} catch (Throwable e) {
logger.error("setCche error:{}", cacheKey, e);
}
return false;
}
问题3 : 异常情况下的永不过期,开关配置,预案
如:使用开关
public boolean setCache(String cacheKey, Object orderInfo) {
try {
long expireTimeSec = AppSwitch.getOrDefault(cacheKey, 60);
redisClient.set(cacheKey, orderInfo, expireTimeSec);
return true;
} catch (Throwable e) {
logger.error("setCche error:{}", cacheKey, e);
}
return false;
}
效率提升:本地缓存
即多级别缓存:
- 先查询本地缓存
- 再查询第三方缓存,如redis缓存
- 若缓存没有,则再访问数据库
- 更新缓存
适合业务
- 读多写少
- 高并发访问,对rt要求高
- 热点数据明显的
监控改进
- redis集群的监控:读、写、内存、磁盘、CPU等
- 业务监控
- redis使用的读写异常量,rt波动异常