缺点
- 缓存和数据库双写一致性问题
- 缓存雪崩问题
- 缓存击穿问题
- 缓存的并发竞争Key的问题
缓存和数据库 双写一致性
解决方案:
首先采取合适的更新策略,先更新数据库 ,再删除缓存 。
其次可能因为存在删除缓存失败的问题,提供一个补偿措施:例如 使用 消息队列
缓存 雪崩
即缓存同一时间大面积失效 ,这时候又来了一拨请求 ,结果都落到了数据库上 ,导致数据库连接异常
解决方案:
- 给缓存加上 随机的失效时间,防止集体失效
- 使用 互斥锁,但是该方法吞吐量明显下降
- 双缓存,缓存A过期时间为20分钟,缓存B不设置过期时间 。自己做缓存预热
缓存穿透
即黑客故意去请求缓存中不存在的数据,导致请求全都落在了数据库上,是的数据库发生连接异常
解决方案:
- 利用 互斥锁,缓存失效的时候,先去获取锁,得到锁了再去请求数据库。没得到锁,则休眠一段时间,重试
- 采用 异步更新 策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前先加载缓存)操作。
- 提供一个可以迅速判断请求是否有效的 拦截机制。比如:布隆过滤器,内部维护一系列合法的有效的 key。迅速判断出携带的Key是否合法有效。如果不合法,则直接返回。u1
缓存的并发竞争Key问题
解决方案:
- 如果对这个key的执行 不要求按照顺序 ,那么准备一个分布式锁,大家去抢锁,抢到锁就做Set操作即可 ,比较简单。
- 如果对这个key的执行 要求按照顺序
假设有一个key1,系统A要将key1 设置为valueA,系统B要将key1 设置为valueB,系统C要将key1 设置为valueC。期望key1的value值按照 valueA–valueB–valueC 的顺序进行变化。这时候我们在数据写入数据库的时候,应该保存一个时间戳。