缓存预热、击穿、雪崩、更新

缓存是为了提升应用响应时间、提升用户体验的。但是缓存会出现雪崩、击穿、穿透等问题,这里就简单聊聊缓存预热、缓存更新、缓存雪崩几个问题。


缓存预热

缓存预热指的是用户请求数据前,先将数据加载到缓存系统中,用户查询事先被预热的缓存数据,以提高系统查询效率。缓存预热一般有系统启动,加载,定时加载等方式。通常来讲,系统中一些经常使用的数据,一些高并发热点数据,可以先预热到缓存中;对一些同步请求耗时过长的请求数据,可以事先预热到缓存中。

缓存预热后,一般可以达到如下几点效果:

  • 以减少用户请求响应时间,提升用户体验
  • 减少应用数据库层面的压力

缓存更新

缓存更新指在数据发生前变化后,及时将变化后的数据更新到缓存中,常见的缓存更新策略有以下4种。

  • 定时更新:是将底层数据库内的数据更新到缓存中,该方法比较简单,适合需要缓存的数据量不是很大的应用场景。

  • 过期更新:定时将缓存中过去的数据更新为最新数据,并更新缓存的过期时间。
  • 写请求更新:在用户有写请求时,先写数据库同时更新缓存,这适用于用户对缓存数据和数据库的数据有实时强一致性要求的情况。
  • 读请求更新:在用户有读请求时,先判断该请求数据的缓存是否过期或存在,如果不存在或已过期,则进行底层数据库查询,并将查询结果更新到缓存中,同时将查询结果返回给用户。

缓存雪崩

缓存雪崩指在同一时刻,由于大量缓存失效,导致大量原本应该访问缓存的请求都去查询数据库,而对数据库的CPU和内存造成巨大压力,严重的话会导致数据库宕机从而形成一系列连锁反应,使整个系统崩溃。针对缓存雪崩,一般由以下三种处理方法。

  • 请求加锁:对于并发量不是很多的应用,使用请求加锁排队的方法,防止过多请求数据库。
  • 失效更新:为每一个缓存数据都增加过期标记来记录缓存数据是否失效,如果缓存标记失效,则更新数据缓存。
  • 设置不同的失效时间:为不同的数据设置不同的缓存失效时间,防止在同一时刻有大量的数据失效。

缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库CPU和内存压力瞬间增大,从而影响数据库正常使用的问题。针对缓存击穿,一般的解决方法如下

  • 热点数据永不过期:对于热点数据,不设置过期时间,避免数据过期时造成的过多请求到数据库。
  • 请求加锁并失效更新:应用未从缓存中请求到数据,则加锁访问应用数据库,并将数据缓存到缓存数据库中,返回应用数据,释放锁。之后的请求便可直接从缓存中取到数据,不用再去到应用数据库中请求数据。

缓存击穿和缓存雪崩类似,但有不同。缓存击穿高并发访问同一个数据,给数据库造成压力;缓存雪崩是指大量应用数据同时失效。


缓存穿透     

缓存穿透指由于缓存系统故障或者用户频繁查询系统中不存在的数据,而这时请求穿过缓存不断被发送到数据库,导致数据库过载,进而引发一连串并发问题。比如用户发起一个name为lisi的请求,而在系统中并没有名为lisi的用户,这样就导致每次查询时在缓存中都找不到该数据,然后去数据库中再查询一遍,由于lisi用户本身在系统中不存在自然返回null,导致请求穿过缓存频繁的查询数据库,已在用户频繁发送该请求时,将导致数据库系统负载增大,从而可能引发其他问题。

常用的缓存穿透问题的方法,有布隆过滤器和cache null策略

  • 布隆过滤器:指将所有可能存在的数据都映射到一个足够大的bitmap,在用户发起请求时,首先经过布隆滤器的拦截,一个一定不存在的数据会被这个布隆过滤器拦截,从而避免对底层存储系统带来查询上的压力。

  • cache null策略:如果一个查询返回的结果为null,那可能是数据不存在,也可能是系统故障。我们仍然缓存这个null结果,但他的过期时间会很短,通常不超过5分钟,在用户再次请求该数据是直接返回null,而不会继续访问数据库,从而有效地保证数据库的安全。其实cache null策略的核心原理是在缓存中记录一个短暂的数据,在系统中是否存在的状态,如果不存在再直接返回那不再查询数据库,从而避免缓存穿透的数据库上。

猜你喜欢

转载自blog.csdn.net/magi1201/article/details/115263451