ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

缓存击穿和缓存穿透

2021-10-19 16:34:58  阅读:122  来源: 互联网

标签:缓存 redis 击穿 穿透 user key mysql id


缓存击穿和缓存穿透

1、缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解决方案:

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

2、缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

解决方案:

  1. 设置热点数据永远不过期
  2. 加锁
public User findUserById(Integer id) {
    User user = null;
    String key = CACHE_KEY_USER + id;

    // 1、先从 redis 中查询,如果有结果,直接返回,如果没有,再去查询 mysql
    user = (User) redisTemplate.opsForValue().get(key);

    if (user == null) {
        // 2、进来就先加锁,保证一个请求,让外面的 redis 等待一下,避免击穿mysql
        synchronized (UserServiceImpl.class) {
            user = (User) redisTemplate.opsForValue().get(key);
            // 3、 再次查询redis 还是 null, 就可以去查询 mysql 了(mysql默认有数据)
            if (user == null) {
                // 5、redis 里面没有,查询Mysql
                user = userMapper.selectByPrimaryKey(id);
                if (user == null) {
                    // 6.1、redis + mysql 都没有数据
                    return user;
                } else {
                    // 6.2 、mysql中有数据 ,需要将数据写回redis,保证下一次的缓存命中率
                    redisTemplate.opsForValue().setIfAbsent(key, user, 7, TimeUnit.DAYS);
                }
            }
        }
    }
    return user;
}

标签:缓存,redis,击穿,穿透,user,key,mysql,id
来源: https://www.cnblogs.com/codertl/p/15425193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有