说起缓存大家并不默生,今天就有一段实际代码来给大家讲讲如何写一段简单高可用代码
@overwride
public UserInfo searchUser(String userNo){
UserInfo user = dao.get(userNo);
return user;
}
就这一行代码,也许做为初缓程序员来说是一行最简单不过的了。但是对于我们中级程序员来说,就要把这一行代码进行升级,会写成如下代码:
@Override
public UserInfo searchUser(String userNo){
String key = "user_" + userNo;
String userStr = redis.get(key);
if(StringUtils.isNotBlack(userStr)){
return JsonUtils.toBean(userStr, UserInfo.class);
}
UserInfo user = dao.get(userNo);
if(user != null){
redis.set(key, JsonUtils.toJson(user));
}
return user;
}
这种代码可能现在普遍程序员的写法,但是就偏偏最普通的代码往往埋下了黑手,当并发很高的时候会击穿缓存,而直接读取数据库,这样对数据库造成很大压力。所以就会产生下面代码
@Override
public synchronized UserInfo searchUser(String userNo){
String key = "user_" + userNo;
String userStr = redis.get(key);
if(StringUtils.isNotBlack(userStr)){
return JsonUtils.toBean(userStr, UserInfo.class);
}
UserInfo user = dao.get(userNo);
if(user != null){
redis.set(key, JsonUtils.toJson(user));
}
return user;
}
这样好是好,但是这个有个排队锁,也就是整个查询性能会大大下降,对于查询缓存也进行了排队,所以对这段代码再次进行升级
@Override
public UserInfo searchUser(String userNo){
String key = "user_" + userNo;
String userStr = redis.get(key);
if(StringUtils.isNotBlack(userStr)){
return JsonUtils.toBean(userStr, UserInfo.class);
}
synchronized(this){
UserInfo user = dao.get(userNo);
if(user != null){
redis.set(key, JsonUtils.toJson(user));
}
}
return user;
}
这样是不是感觉很好,但是这个也同样存在问题,原因就在高并发下排队读取了数据库,对数据库造成压力。所以需要再次升级
@Override
public UserInfo searchUser(String userNo){
String key = "user_" + userNo;
String userStr = redis.get(key);
if(StringUtils.isNotBlack(userStr)){
return JsonUtils.toBean(userStr, UserInfo.class);
}
synchronized(this){
String userStr = redis.get(key);
if(StringUtils.isNotBlack(userStr)){
return JsonUtils.toBean(userStr, UserInfo.class);
}
UserInfo user = dao.get(userNo);
if(user != null){
redis.set(key, JsonUtils.toJson(user));
}
}
return user;
}
这样已经接近完美,但是程序员不能每天的经历是写一堆关于没用的代码。那我们就用模板方式实现。
@Override
public UserInfo searchUser(String userNo){
String key = "user_" + userNo;
return redisCacheTemplate.find(key, 10000L, UserInfo.class, new CacheLoadable<UserInfo>() {
@Override
public UserInfo load() {
return dao.get(userNo);
}
});
}
是不是很简单,具体Template实现可加微信