Redis问题
缓存问题
缓存是在第一次加载的数据进行复用,将数据存放指定地点以便下次加载使用。可防止多访问同一 数据库 而产生的堵塞,也能减轻 数据库 的压力!
Java缓存
缓存雪崩
原因
原有缓存失效(或者未加载到缓存中),因此 访问过程会跨越缓存直接访问 数据库,这一过程很有可能会导致 数据库 宕机(cpu、内存 高负载)
解决方案
加锁
public Users getByUsers(Long id) {
// 1.先查询redis
String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()[1].getmethodName()+ "-id:" + id;
String userjson = redisService.getString(key);
if (!StringUtils.isEmpty(userjson)) {
Users users = JSONObject.parSEObject(userjson, Users.class);
return users;
}
Users user = null;
try {
lock.lock();
// 查询db
user = userMapper.getUser(id);
redisService.setSet(key, JSONObject.toJSONString(user));
} catch (Exception e) {
} finally {
lock.unlock(); // 释放锁
}
return user;
}
缓存穿透
原因
当用户查询指定数据 且 数据库 中恰好也没有,此时缓存自然也不会有。这样就导致 重复查询 都会访问数据库,类似的查询都会绕过缓存直接查数据库!
解决方案
public String getByUsers2(Long id) {
// 1.先查询redis
String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()
[1].getmethodName()+ "-id:" + id;
String userName = redisService.getString(key);
if (!StringUtils.isEmpty(userName)) {
return userName;
}
System.out.println("######开始发送数据库DB请求########");
Users user = userMapper.getUser(id);
String value = null;
if (user == null) {
// 标识为null
value = "";
} else {
value = user.getName();
}
redisService.setString(key, value);
return value;
}
缓存击穿
原因
在某一时间点 突然以超高并发进行访问 过期的key,导致 缓存被击穿
突然高频访问的key 称为 热点数据
解决方案
- 使用锁,单机
synchronized
、lock
等,分布式用 分布式锁- 缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存
分布式锁问题
死锁
原因
通过setnx命令,创建的key-value值,若未设置有效期;或者是持有锁的客户端崩溃未释放锁。都很有可能会卡住
解决方案
先
GET
命令 查看锁是否超时,超时则可使用getset
命令 获取锁
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。