缓存击穿
缓存击穿是对热点数据大批量请求时,这个热点数据的key过期了,导致大量请求涌入到数据库中,导致数据库压力骤增。
解决方案:在缓存失效后更新缓存时先获取分布式锁,拿到锁的线程可以查询数据库并更新缓存数据,如果获取分布式锁失败,证明有线程正在查询数据库并更新,每隔一秒重试拿锁重试三次,三次后可以返回状态:数据正在更新,请稍后重试。
缓存穿透
缓存穿透是访问一个数据库和缓存中都不存在的数据,而用户不断发起请求,比如访问id为-1或者一个非常大的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:在接口层增加校验,id<=0的数据直接拦截,在缓存中取不到的数据,在数据库中也没有取到,设置为缓存为key-null,缓存时间设置小一点,如30秒(防止正常情况下也无法使用数据),这样可以防止攻击者用同一个id暴力攻击。
缓存雪崩
缓存雪崩是指缓存中批量数据同时到期,而查询数量巨大,引发数据库查询压力过大甚至宕机。和缓存击穿不同的是,缓存击穿是并发查一条数据,而缓存雪崩是不同的数据都过期了,涌进数据库导致数据库压力剧增。
解决方案:缓存过期时间设置随机,防止同一时间大量数据同时过期现象发生。
设置热点数据永不过期,定时刷新,读取数据时
- 没有缓存,先获取分布式锁再查询数据库,缓存数据
- 有缓存并且还没到刷新时间,直接读缓存;
- 有缓存并且到了或超过了刷新时间,直接读缓存并异步刷新缓存,更新缓存时间;