1.缓存穿透
缓存穿透的表现是大量的数据请求在缓存中查询不到,直接访问数据库造成数据库,原因可能如下:1.数据在缓存中确实不存在,需要再次查询数据库;2.黑客恶意攻击,使用非正常的url访问服务器恶意攻击数据库。(透过缓存直接到达数据库)
解决办法如下:
- 查询不到的数据设置为Null存储在缓存中,下次访问相同的数据时直接返回(并设置一个较小的过期时间)
- 设置可以访问的名单(白名单),借助bigmap,将白名单id做偏移量,每次访问时首先与bigmap里的数据进行比较,若id不存在则直接拦截访问。
- 布隆过滤器,在请求数据时,首先查询数据是否存在,查询时使用布隆算法:将查询id传入一个hash函数计算结果在[0,9]之间,标识该位为1,查询时计算id的hash值,以该值为下标取出数组中的值,如果为0,表示数据不存在,如果为1则数据可能存在。注意,这里描述的是可能存在,因为hash值在计算的过程中,可能存在重叠(不同的id得到同一个hash),所以查询时如果表明数据存在,也不能保证缓存中真的存在该数据。从上述描述也可以看出,布隆算法使用的数组长度为10,这就不可避免该算法存在一定的错误率,如果需要降低错误率,可用空间换取,适当扩大bit数组的长度。
- 进行实时监控,当缓存命中率突然降低时,排除访问对象,防止黑客恶意攻击并将其加入黑名单,禁止其继续访问。
2.缓存击穿
缓存击穿发生时redis正常运转,造成击穿的原因是同一时间有大量的请求访问同一个数据,而在该时间点所需要访问的数据过期,使得所有的请求直接到达数据库。(大量请求集中在一个点,击穿)
解决办法如下:
- 预先设置热点数据,在redis访问高峰之前,把热们数据放入redis缓存,增大过期时间或者设置为永不过期。
- 进行实时调整监测,及时更新热点数据的过期时间。
- 采用锁机制,当redis缓存中查不到数据时对数据进行锁定,避免其他线程继续查询,当某个线程从数据库查询到数据后及时更新到缓存中。
3.缓存雪崩
在极短的时间内,大量缓存key值过期,使得数据在缓存查询不到(redis宕机),直接到达数据库。(redis宕机导致后续所有的操作都出现问题-雪崩)
解决方法如下:
- 采用多级缓存,使一个缓存宕机时还有备用缓存代替其工作。
- 使用锁和队列,保证同一时刻不会有多个线程请求数据,此方法可能导致效率降低,不适合并发情况。
- 设置过期标志更新缓存,key快要过期的时候提醒线程对key的过期时间进行更新。
- 分散缓存数据的过期时间,避免出现大量Key同时过期的情况发生。