Redis实战场景---缓存穿透

懒驴 2022年01月14日 363次浏览

文章《Redis的配置类以及Redis的操作工具类》描述了SpringBoot集成Redis已经Redis的一般操作类,现在将来看看Redis在项目中的运用场景---缓存穿透。

Redis缓存的使用极大地提升了应用程序的整体性能和效率,特别是在查询数据方面,大大减低了查询数据库的频率,但同时也带来了一些问题,其中比较典型的问题包括缓存穿透、缓存血崩和缓存击穿。此次将对“缓存穿透”做详细讲解。

1. 什么是缓存穿透

首先我们来看看项目中使用缓存Redis查询数据的正常流程,如下图:

Redis缓存正常查询的大致流程图


从上图中可以看出,前端用户要访问获取数据时,后端首先会在Redis中查询,如果查询到数据,则直接将数据返回给用户,流程结束;如果在缓存中没有查询到数据,则前往数据库中查询,此时如果能查询到数据,则将数据返回给用户,同时将数据加入到Redis缓存中,流程结束,如果在数据库中没有查询到数据时,则返回null,流程结束。 这个正常查询缓存的流程刚开始看似乎没什么问题,但是仔细看最后一个步骤:“当查询数据库时如果没有查询到数据,则直接返回null给前端,流程结束”,如果前端频繁发起访问请求时,恶意提供数据库中不存在的Key,则此时数据库中查询到的数据将永远为Null。由于Null数据是不存入缓存中的,因而每次访问请求时将查询数据库,如果此时恶意攻击,发起“洪流”式的查询,则很有可能会对数据库造成极大的压力,甚至压垮数据库。这个过程称之为“ 缓存穿透 ”,顾名思义,就像是“永远越过了缓存而直接永远的访问数据库”。

2.其它典型问题

Redis缓存的使用在给应用带来整体性能和效率提升的同时,也带来了一定的问题。例如另外两大典型的问题,分别是缓存雪崩和缓存击穿

  • 缓存雪崩:指的是在某个时间点,缓存中的Key集体发生过期失效致使大量查询数据库的请求都落在了DB数据库上,导致数据库负载过高,压力暴增,甚至有可能“压垮”数据库。
    这种问题产生的原因其实主要是因为大量的Key在某个时间点或者某个时间段过期失效所致的。所以为了更好的避免这种问题的发生,一般做法是为这些Key设置不同的、随机的TTL(过期失效时间),从未错开缓存中Key的失效时间点,可以在某种程度上减少数据库的查询压力。

  • 缓存击穿:指缓存中某个频繁被访问的Key(可以称为“热点Key”),在不停的扛着前端的高并发请求,当这个Key突然在某个瞬间过期失效时,持续的高并发访问请求就“穿破”缓存,直接请求数据库,导致数据库压力在某一瞬间暴增。这种现象就像是“在一张薄膜上凿出了一个洞”。

  • 这个问题产生的原因主要是热点的Key过期失效了,而在实际情况中,既然这个Key可以被当作“热点”频繁访问,那么久应该设置这个Key用不过期,这样前端的高并发请求将几乎永远不会落在数据库上。

不管是缓存穿透、缓存雪崩还是缓存击穿,其实它们最终导致的后果几乎都是一样的,即给DB(数据库)造成压力,甚至压垮数据库。而它们的解决方案也都有一个共性,那就是“加强防线”,尽量让高并发的请求落在缓存中,恻然避免直接跟数据库打交道。