xChar
·13 days ago

缓存雪崩

缓存雪崩:当大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机时,如果此时有大量的用户请求,无法在 Redis 中处理,那么这些请求将会直接访问数据库,从而导致数据库压力骤增,严重的话会导致数据库崩溃宕机,进而导致整个系统崩溃。

解决方案:

  • 避免为大量的数据设置成同一个过期时间,我们可以在设置过期时间时添加一个随机数,这样就可以保证数据不会在同一个时间过期了。
  • 互斥锁,如果发现访问的数据不在 Redis 里,就加个互斥锁,保证同一个时间内只有一个请求来构建缓存(从数据库读取数据,再将数据更新到 Redis),当缓存构建完成后,再释放锁。未能获取到互斥锁的请求,要么等待锁释放后,重新读取缓存,要么直接返回空值或者默认值。实现互斥锁时,要设置超时时间,不然某个请求拿到锁后,如果请求发生意外情况而一直阻塞,一直不释放锁,这时其他请求不能拿到锁,整个系统就会出现无响应的现象。
  • 后台更新缓存,业务线程不再负责更新缓存,缓存不必设置有效期,让缓存“永久有效”,并将更新缓存的工作交由后台线程定时更新。

缓存击穿

缓存击穿:如果缓存中的某些热点数据过期了,此时大量的请求访问这些热点数据,就无法从缓存中读取,进而直接访问数据库,导致数据库被高并发请求冲垮。

解决方案:

  • 互斥锁,保证同一时间内只有一个线程更新缓存,未能获取到互斥锁的请求,要么等待锁释放,要么直接返回空值或默认值。
  • 不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据要过期前,提前通知后台线程更新缓存并重新设置过期时间。

缓存穿透

缓存穿透:当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时失效,再去访问数据库,发现数据库中也没有这些数据,没办法构建缓存为后续的请求服务。当有大量这样的请求时,数据库的压力会骤增,进而导致数据库崩溃。

解决方案:

  • 非法请求判断:在请求入口处加入请求参数校验,检查参数是否合理有效,如果是非法参数,直接返回错误,避免进一步访问缓存和数据库。
  • 缓存空值或默认值,针对某些要查询的数据,在缓存中设置一个空值或默认值,这样后续的请求可以直接从缓存中读取到空值或者默认值,返回给应用程序,而不会进一步查询数据库。
  • 布隆过滤器:当用户请求到来时,可以通过查询布隆过滤器来快速判断数据是否存在,如果不存在,就不用再查询数据库了,这样就能保证数据库正常运行。
Loading comments...