redis缓存

缓存穿透
​ 查询一个一定不存在的数据,就会一直去数据库查

​ 解决:null结果缓存,并加入短暂过期时间,实际在配置中让spring.cache.redis.cache-null-value=true

缓存雪崩
​ 大量key在某一时刻都失效,就会将全部请求查询放给数据库

​ 解决:一定要加上过期时间,spring.cache.redis.time-to-live=3600000 即1小时,也可以加上随机过期时间

缓存击穿
​ 一个热点key正好过期,但是大量请求进来,都查数据库

​ 解决:分布式锁

2.9 分布式锁Redisson
 读写锁:
     改数据加写锁,写锁没释放都要等待
     读数据加读锁,读锁没释放写要等待
     保证一定能读到最新数据,修改期间写是排它锁(互斥锁,独享锁),读锁是共享锁
     读+读:相当于无锁,并发读,只会在redis中记录好,所有当前的读锁,他们都会同时加锁成功
     写+读:等待写锁释放
     写+写:阻塞方式
     读+写:有读锁,也要等待
     but:在浏览器访问多个read,会有被阻塞的现象,在等待读,jmeter没有
 闭锁:RCountDownLatch
 信号量:RSemaphore

参考文档

2.10 SpringCache
基本原理(P172)
​ CacheManager(RedisCacheManager)>Cache(RedisCache)>Cache负责缓存的读写

​ 可以解决:缓存穿透和缓存雪崩

​ 不能解决:缓存击穿(默认cache配置),可以让sync=true,即加本地锁,就会进入synchronized方法

​ 也就是,springboot对读模式有处理方法,对于写模式没有(主要加读写锁,或者写多的去数据库别缓存)

// spring中对于缓存是有个分区的概念,就是value,便于删除所有"category"分区的数据
// 代表当前方法的结果需要缓存,如果缓存中有,方法不调用,如果缓存中没有,调用方法,最后将方法的结果放入缓存
@Cacheable(key = "#root.methodName",value = {"category"},sync = true)  
@CacheEvict(value = "category",key = "'getLevelFirstCategorys'")
@CacheEvict(value = "category",allEntries = true)  //所有都删除

缓存数据一致性
双写模式

比如:要更新三级分类菜单,那么更新完后,就把缓存手动改掉

失效模式

比如:要更新三级分类菜单,那么更新完后,就把缓存直接删掉

上面两种其实都有漏洞,比如

​ 双写模式下:两个请求该一个数据,第一个先到,但是第一个超慢,就会把第二个要改的数据在缓存中覆盖。可以加锁避免这种情况,只有一个写请求执行完,才放另一个进来,也可以给过期时间,就能最终一致

​ 失效模式:三个请求,第一个写1号数据然后删,第二个是写2号数据然后删,但是时间久,第三个进来读发现没有就读数据库,读到之后准备写缓存碰巧很久,久到2号数据修改完成都删了,此时第三个请求只包含1号的修改数据,然后就把读到的缓存起来,正好漏过2号数据的修改。可以加锁避免这种情况,因为同时存在读写

​ 一句话,经常修改的数据注解去读数据库,非要缓存的加过期时间,加读写锁,写都排队就行。在商城系统中,对于缓存的数据,不应该是实时性一致性太高的,所以只需加上过期时间,保证一天都能拿到最新数据即可,不用过度设计。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值