黑马程序员Redis入门到实战教程,深度透析redis底层原理+redis分布式锁+企业解决方案+黑马点评实战项目
总时长 42:48:00 共175P
此文章包含第40p-第p45的内容
文章目录
- 缓存穿透
- 解决方案
- 缓存空对象
- 布隆过滤
- 解决方案实现
- 缓存穿透总结
- 缓存雪崩
- 解决方案
- 缓存击穿
- 解决方案
- 解决方案实现
- 互斥锁代码实现
- 逻辑过期代码实现
缓存穿透
解决方案
缓存空对象
布隆过滤
用hash算法存储二进制数据在布隆过滤器里
如果布隆过滤器里不存在数据库里一定不存在,
如果布隆过滤器里存在数据库里不一定存在
解决方案实现
空值的缓存时间短一点 两三分钟
这里用shopJson != null不太容易理解 用 shopJson == “” 比较好
缓存穿透总结
缓存雪崩
解决方案
缓存击穿
解决方案
对比
cep定理 在一致性和可用性中做选择
解决方案实现
setnx命令来实现互斥锁 只有key不存在的时候才能往里写数据
释放锁的时候直接删除就行 del key
ps:如果程序出问题了,无人再去释放这个锁了,就会产生死锁
可以设置一个有效期(如10秒)来兜底,否则可能会发生死锁问题 【有效期也不能太短(逻辑未执行完就释放了)】
互斥锁代码实现
加锁和释放锁代码↓
不要直接返回flag,容易返回null,会报空指针异常
return BooleanUtil.isTrue(flag); 相当于 return(flag != null)&& flag;
原来逻辑
新逻辑
这里使用了递归(ps:企业开发禁止写递归哦)
模拟延时
使用jmeter进行并发测试
只触发了一次数据库查询
逻辑过期代码实现
两种方法 一种是将shop对象类继承RedisData
一种是组合
ps:组合(组合复用)优于继承,侵入性低
如果报空指针加上@RunWith(SpringRunner.class)
注意:分布式可以复查,否则会有几率多次查数据库,这里就算多次重建也没影响啊,每个线程都要加锁就决定了并发量不会大。这又不像单例那样规定死了
doublecheck的意义:如果等待的线程缓存未命中,想要获取锁时,刚好缓存重建完毕,redis中已经有数据了,而且锁也被释放了,此时缓存未命中的线程就会获取到锁导致缓存再次重建
写个线程池
直接用之前的方法
这里测试使用20秒 实际最好设置30分钟
ps:这个锁的粒度加的有点大
这里的逻辑过期 是可以在过期之后进行重新加载 使用新的数据 ,这个值一直是存在于redis中的,只是过期之前可能使用的一直是旧数据