缓存穿透
1、缓存穿透是指查询一个缓存中和数据库中都不存在的数据,导致每次查询这条数据都会透过缓存,直接查库,最后返回空。
解决缓存穿透的方法一般有两种,第一种是缓存空对象,第二种是使用布隆过滤器。
缓存击穿
2、缓存击穿是指当缓存中某个热点数据过期了,在该热点数据重新载入缓存之前,有大量的查询请求穿过缓存,直接查询数据库。
解决缓存击穿的方法也有两种,第一种是设置key永不过期;第二种是使用分布式锁。
试试双重检查 来避免 缓存击穿
import cn.hutool.json.JSONUtil; import com.jin.pagehelper.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.math.BigInteger; import java.util.Date; @SuppressWarnings("all") @Service public class RedisService { @Autowired private RedisTemplate redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate; @PostConstruct public void init() { if (redisTemplate.opsForHash().hasKey("employee", "1")) { redisTemplate.opsForHash().delete("employee", "1"); } } public void setValueTest() { redisTemplate.opsForHash().put("employee", "1", JSONUtil.parse( new Employee() .setEmployeeId(BigInteger.valueOf(1)) .setFirstName("jin") .setLastName("jin") .setHireDate(new Date()) ) ); System.out.println("ok"); } public void getOps() throws InterruptedException { Object object = redisTemplate.opsForHash().get("employee", "1"); if (object == null) { synchronized (this) { object = redisTemplate.opsForHash().get("employee", "1"); if (object == null) { System.out.println("redis没有,只能从数据库找"); setValueTest(); } else { System.out.println("并发情况下,从redis拿到了"); } } } else { System.out.println("正常情况下,从redis拿到了"); } } }
自己模拟一个并发情况,做试验。
ExecutorService executorService = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { executorService.submit(() -> { try { redisService.getOps(); } catch (InterruptedException e) { throw new RuntimeException(e); } }); }
标签:缓存,redis,击穿,employee,import,opsForHash,redisTemplate From: https://www.cnblogs.com/wuyicode/p/17834426.html