redis解决缓存雪崩,缓存穿透,缓存击穿代码实现

4 篇文章 0 订阅
3 篇文章 0 订阅

1.防止缓存穿透源码实现

(1)使用的是Google的Bloom Filter
     <1>引入依赖

  <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </dependency>

(2)使用双重验证锁解决高并发环境下的缓存穿透问题

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;
    //springboot自动配置的,直接注入到类中即可使用
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    /**
     * 查询所有学生信息,带有缓存
     * @return
     */
    public List<Student> getAllStudent() {
        //在高并发条件下,会出现缓存穿透
        List<Student> studentList = (List<Student>)redisTemplate.opsForValue().get("allStudent");
        if (null == studentList) {
            //5个人, 4个等,1个进入
            synchronized (this) {
    //双重检测锁,假使同时有5个请求进入了上一个if(null == studentList),
    //加了锁之后one by one 的访问,这里再次对缓存进行检测,尽一切可能防止缓存穿透的产生,但是性能会有所损失
                studentList = (List<Student>)redisTemplate.opsForValue().get("allStudent");
                if (null == studentList) {
                    studentList = studentMapper.getAllStudent();
                    redisTemplate.opsForValue().set("allStudent", studentList);System.out.println("请求的数据库。。。。。。");} else {//System.out.println("请求的缓存。。。。。。");
                }}} else {System.out.println("请求的缓存。。。。。。");
        }return studentList;}}    

2.防止缓存雪崩、缓存击穿源码实现

(1)加互斥锁,互斥锁参考代码如下:

 static Lock reenLock = new ReentrantLock();
   public List<String> getData04() throws InterruptedException {
       List<String> result = new ArrayList<String>();
       // 从缓存读取数据
       result = getDataFromCache();
       if (result.isEmpty()) {
           if (reenLock.tryLock()) {// tryLock()方法介绍:尝试获取锁,是否得到锁,得到锁往下执行true,没有绝不等直接返回false(锁已被其他线程获取),也可以设置tryLock(等待时间);
               try {
                System.out.println("我拿到锁了也需要获取下缓存,通过再从DB获取数据库后写入缓存");
                result = getDataFromCache();
              
                   // 从数据库查询数据
                   result = getDataFromDB();
                   // 将查询到的数据写入缓存
                   setDataToCache(result);
               
               } finally {
                   reenLock.unlock();// 释放锁
               }
           } else {
               result = getDataFromCache();// 先查一下缓存
               if (result.isEmpty()) {
                 System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
                   Thread.sleep(100);// 小憩一会儿
                   return getData04();// 重试
               }
           }
       }
       return result;
   }

3.缓存穿透、雪崩、击穿最终结果都是对数据库造成压力

(1)不管是使用双重检索还是加互斥锁,都是为了减轻DB压力
(2)一般情况下使用加互斥锁来实现

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值