Redis 的缓存穿透、击穿、雪崩
缓存穿透:重复查询一条数据,redis缓存中没有,数据库中也没有。就容易照成缓存击穿。
解决方案:
1、前端做出限制,例如查询id为-1的数据,这一条很明显。redis中和mysql中都不可能查询到,所以在前端或service(防止有人跳过前端,直接以ip/project?id=-1请求)做出相应拦截(拦截id<0)。
2、如查询一次发现这种情况,可以将它缓存到redis中,但是建议5分钟后自动销毁(防止内存被占满)。
3、用布隆过滤器,查询不到的值设置为0.再次查询就直接拦截。
缓存击穿:某条数据缓存中没有,数据库中有。在同一时间,多个用户同时查询,造成数据库压力过大,严重情况数据库可能直接挂掉。
解决方案:
1、添加互斥锁:
- ReentrantLock公平锁
- 根据key值加锁,这样线程之间会不影响,不会因为某一个线程获取了锁,其它线程就处于等待时间,也就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据
2、设置热点数据永不过期(物理上的不过期、"逻辑上"的不过期(缓存到期动态构建缓存))
缓存雪崩:很多条数据的过期时间到了,从而导致数据库查询量巨大,和缓存击穿不同,这是多条数据同时过期。
解决方案:
1、设置热点数据不过期
2、在缓存的过期时间末尾追加 随机时间1-3min,尽量不能让热点数据同一时间失效。
3、可设置分布式缓存数据库,将热点数据库分别放到不同的缓存数据库中,避免某一点因压力过大而down掉。
缓存与数据库一致性:在数据库中插入一条新的记录之后,查询redis。结果redis中没有,重启redis之后,redis中才会生效。
解决方案:
1、插入数据库的同时,手动将该条数据插入到缓存中。
2、设置定时任务,清空redis中的数据,然后再次保存。