缓存穿透、缓存击穿和缓存雪崩

 缓存处理流程

缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。一般情况下redis不会有缓存,就会去访问数据库,大量访问造成数据库压力大从而崩溃。

解决方案:1、对ID的正确性进行校验,不正常的ID无法进入后台。

2、对于不存在的数据缓存为null,超时时间设置短一点。

 

缓存击穿

当我们缓存key设置过期时间,恰巧在这一刻这个key在某一刻被高并发的访问,把所有的请求都打到了DB中这就可能会导致DB挂了。

解决方案:

使用同步方式锁,单机用synchronized,lock可重入锁等,分布式则用redis的setnx

String getValue(String key) {
	String value = redis.get(key);
	if (value == null) {
		String lockKey = "lock_" + key;
		if (redis.setnx(lockKey, "1")) {
			//设置超时时间
			redis.expire(lockKey, 60);
                        //数据库取值
			value = db.get(key);
			redis.set(key, value);
			redis.del(lockKey);
		} else {
			//如果有其他线程在操作,就等候50ms再次尝试获取
			Thread.sleep(50);
			get(key);
		}
	}
	return value;
}

 能保证一致性,但是代码复杂度增大,存在死锁的风险

 

采用缓存物理不过期,逻辑过期方式,在key对应的value设置一个timeout字段。如果检测到存的时间超过过期时间则异步更新缓存。

String getValue(final String key) {  
        T t = redis.get(key);  
        String value = t.getValue();  
        long timeout = t.getTimeout();  
        // 当逻辑的超时时间到了时,异步构建缓存  
        if (timeout <= System.currentTimeMillis()) {  
            threadPool.execute(new Runnable() {  
                public void run() {  
                    String lockKey = "lock_"+key;  
                    if (redis.setnx(lockKey, "1")) {
                        redis.expire(lockKey, 60);
                        String dbValue = db.get(key);  
                        redis.set(key, dbValue);  
                        redis.del(lockKey);  
                    }  
                }  
            });  
        }  
       return value;  
}

不会阻塞线程、高性能,但是数据库和缓存可能会存在数据不一致。

 

缓存雪崩

缓存雪崩是指在某一个时间段,缓存集中过期失效。请求都去访问数据库导致数据库崩溃。

解决方案:

1、不同的数据设置不同的超时时间

2、和缓存击穿一样的解决方式。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值