缓存穿透
大量请求的key根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。
解决方法:
1、首先做好请求参数校验,一些不合法的参数请求直接快速失败,抛出异常信息返回给客户端。
2、缓存无效key,如果缓存和数据库都查不到某个key的数据,就缓存该数据。
(注:可以解决请求的key变化不频繁,也有可能会导致Redis中缓存大量无效的key)
3、布隆过滤器,把所有可能存在的请求的值都存放到布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中;不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走正常的流程。
缓存雪崩
缓存在同一时间大面积的失效,后面的请求都直接落到数据库上,造成数据库短时间内承受大量请求。
解决方法:
1、Redis服务不可用的情况,采用Redis集群,避免单机出现问题导致整个缓存服务都没有办法使用。
2、限流,避免同时处理大量的请求。
3、热点缓存失效情况,设置不同的失效时间,比如随机设置缓存的失效时间。
4、缓存永不失效。
如何保证缓存和数据库数据一致性?
结论:引入缓存之后,如果为了短时间内的不一致性问题,选择让系统设计变得更加复杂的话,完全没有必要。因此,某种意义上无法保证缓存和数据库数据的一致性,只能尽可能缩短不一致性时间和概率。
解决方法:采用Cache Aside Pattern(旁路缓存模式),遇到写请求,先更新DB,然后直接删除cache。
如果更新数据库成功,而删除缓存这一步失败的情况的话:
1、缓存失效时间变短:让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。
2、增加cache更新重试机制:如果cache服务当前不可用导致缓存删除失败的话,就隔一段时间进行重试,重试次数可以自主设定。如果多次重试还是失败的话,可以把当前更新失败的key存入队列中,等缓存服务可用之后,再将缓存中对应的key删除即可。