缓存穿透
缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。
解决方案
-
缓存空对象,为避免占用资源,一般过期时间会比较短 优点:实现简单,维护方便 缺点:额外的内存消耗,可能造成短期的不一致 -
布隆过滤 优点:内存占用较少,没有多余key 缺点:实现复杂,存在误判可能 -
增强id的复杂度,避免被猜测id规律 -
做好数据的基础格式校验 -
加强用户权限校验 -
做好热点参数的限流,基于二八原则,我们通常只会缓存常用的那 20% 的热点数据 -
设置可访问白名单,用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmaps里面的id进行比较,如果访问id不在bitmaps中,进行拦截,不允许访问 -
实时监控,当发现redis的命中率开始急剧降低时,需要及时排查访问对象和和访问数据,和运维人员配合,设置黑名单
设计思想
代码实现
public ResponseEntity<Object> getUserById(String id) {
// 从redis中根据key查询用户列表信息
String user = (String) redisTemplate.opsForValue().get("user:" + id);
// 如果用户信息不为null、""、"tn",则存在,转化为Issa
if (StrUtil.isNotBlank(user)) {
Issa issa = JSONUtil.toBean(user, Issa.class);
return ResponseEntity.ok(issa);
}
if (user != null) {
return ResponseEntity.status(400).body("没有用户信息");
}
// 查询所有用户信息
Issa userById = userMapper.getUserById(id);
// 判断是否为空
if (userById == null) {
redisTemplate.opsForValue().set("user:" + id, "", 10, TimeUnit.SECONDS);
return ResponseEntity.status(405).body("没有任何一个用户的信息");
}
// 转化为字符串
String issasStr = JSONUtil.toJsonStr(userById);
// 保存到redis中,并设置超时时间作为兜底方案
redisTemplate.opsForValue().set(USER_LIST, issasStr, 60, TimeUnit.SECONDS);
// ok
return ResponseEntity.ok(userById);
}
原文始发于微信公众号(步尔斯特):Redis三大难点之缓存穿透
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/47875.html