redis缓存穿透,缓存击穿,缓存雪崩以及缓存一致性

tech2024-07-14  58

一、缓存穿透

查询不存在的数据,请求会直接到数据库。

解决:

(1)缓存空值

(2)布隆过滤器BloomFilter

二、缓存击穿

热点key突然失效,大量请求到达数据库

解决:

分布式锁

三、缓存雪崩

大部分key失效

解决:

设置逻辑过期时间

错开物理过期时间

public class RedisCache { Jedis jedis = new Jedis("redis://localhost:6379/9"); DbService db = new DbService(); //redis初始化,bloomFilter加值 //数据库添加值,缓存添加值,bloomFilter加值 //数据库删,缓存删,重构bloomFilter BloomFilter<CharSequence> bloomFilter= BloomFilter.create(Funnels.stringFunnel(),10000, 0.001); public String query(String key) { //缓存穿透 if (!bloomFilter.mightContain(key)) { return "空数据"; } //查询缓存 String value = jedis.get(key); //缓存命中 if (value != null) { return value; } else { //缓存未命中,查询数据库,在更新缓存。 //分布式锁,防止缓存击穿造成数据库大量访问 jedis.set(key, "threadId", "NX", "PX", 10); //查询缓存 value = jedis.get(key); if (value != null) { return value; } String dbValue = db.query(key); if (dbValue != null) { jedis.set(key, dbValue); return dbValue; } //释放锁 String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList("threadId")); } return ""; } }

 

四、缓存一致性

以为更新数据库和更新缓存不是原子操作,所以多线程会出现问题。

1.先更新数据库再更新缓存

如果线程A更新数据库 ->线程B更新数据库->线程B更新缓存->线程A更新缓存

会造成数据不一致,先更新缓存再更新数据库同理。

2.先删除缓存再更新数据库

如果线程A删除缓存->线程B查询发现缓存不存在,查询数据库并更新缓存->线程A更新数据库

会造成数据不一致。

3. 先更新数据库再删除缓存

缓存刚好失效 ->线程B查询发现缓存不存在,查询数据库->线程A更新数据库->线程A删除缓存>线程B删除缓存

这种情况出现概率非常小

最新回复(0)