缓存击穿、缓存穿透、缓存雪崩等并发问题的解决思路
在微服务应用中,每个细微的问题都可能由于并发
被无限放大。
在并发场景
下,比较常见的有:秒杀活动中的商品超卖问题、数据冷热分离处理、缓存/数据库双写一致性问题、缓存击穿、缓存穿透、缓存雪崩问题等。
在Java基础中,解决并发的思路就是锁,而锁的本质就是将并发执行串行化
,在微服务应用中,synchronized关键字、ReentrantLock类提供的各种lock方法均已失效,因为这些锁的作用域是一个服务的单个节点,对其他节点则无法生效。
单机锁不够用了,大佬们就弄了个分布式锁——Redisson/Zookeeper等框架。Redisson选择了AP、Zookeeper选择了CP,因此Redisson性能相对更快,Zookeeper则有效地保证了数据一致性。
用分布式锁,锁住商品id,每个商品则只会被售卖一次,
避免商品超卖
。用Redis缓存热门数据,并发请求会先去缓存中查询,未查询到再查询数据库,实现
数据冷热分离
。保证
缓存/数据库双写一致性
,则是将数据库读+写入缓存这两个操作加上读写锁中的读锁,修改操作加上读写锁中的写锁。读写锁是一种并发控制机制,同时支持读和写操作。在读写锁中,读操作可以并发进行,而写操作会独占锁。读锁也称为共享锁,是一种允许多个线程同时读取数据的锁。缓存数据的有效时间增加随机偏移量,避免缓存数据同时过期引发
缓存击穿
带来的数据库压力。
缓存穿透
则是频发查询缓存和数据库不存在的数据,这种情况往往伴随着恶意攻击,可以采取Bloom filter 等技术快速判断一些非法请求、增加参数校验、在缓存中设一个空置返回。
缓存雪崩
则是Redis扛不住压力的请求量并发访问造成Redis崩溃,进而引起整个系统的大面积功能瘫痪,这种可以采取Redis Cluster集群+Sentinel控流降级应对。