缓存穿透是用户访问一个不存在的key,导致请求穿透到数据库。
  问题关键是程序上要识别出这个key是一个错误key,不是由系统生成的key。每次添加或删除缓存时维护一个key字段查询过滤器,例如:布隆过滤器、HashSet。这样在访问缓存前,可以对key先进行查询过滤,判断key是否存在,再往下执行业务逻辑。
  另一种办法是把空结果缓存,key不存在有两种情况,一是数据库存在,但key缓存过期了,或者还没把数据设置缓存,二是数据库没记录,key不存在。要把这两种情况区分开,程序才不会误判。对于第二种,要把key缓存起来,值设置为空字符串返回,过期时间不宜设置太长,例如10分钟内,因为数据库虽然现在没记录,但将来可能有,设置一定有效期是有必要的,既能够保持数据最终一致,又能解决穿透问题。第一种是数据库存在,key不存在,返回的是null,继续往下执行业务逻辑。
 
  缓存雪崩是指大范围key在同一时间失效,请求同一时间落到数据库。
  在每个key设置基础失效时间上加上一个随机失效时间,例如5分钟内的随机数,这样就可以把失效时间分散开,避免集中在一个时间点上失效。
 
  缓存击穿是一个热点key突然缓存时间到期失效,大量请求落到数据库。
  既然问题是热点key缓存到期失效引起的,如果程序能在key临近到期时,主动去更新缓存延期,就能避免被击穿。在设置缓存时可以把到期时间记录到缓存里,每次读缓存时取出到期时间,判断距离当前时间还有多久失效,假如已到达设定的阈值(如:1分钟),则拉取最新数据更新缓存。建议根据您的业务执行时间去设置阈值,保证在阈值内能执行完缓存更新。
  上篇文章说到用缓存双删来更新缓存,但在缓存删掉后,读业务没了缓存层,在瞬间将面临大流量击穿到数据库。假如热点key设置了两份缓存分别是C1和C2,并且C2过期时间要比C1长,当C1缓存不存在时,用C2缓存来缓冲。虽然像解决了问题,但C1被删了,只能通过后台作业或者消费队列去更新C1,这样做缓存双删就失去原来的作用了。所以不能光用缓存来档流量,也要在原来缓存层上加入限流,把流量层层削弱,让少部分流量留入数据库,不至于宕机。下篇将讲讲如何限流