高可用:如何避免微服务中的雪崩问题?
在接触缓存的时候,你一定听过缓存雪崩这个概念。
缓存雪崩描述的就是这样一个简单的场景:缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。
举个例子:系统的缓存模块出了问题比如宕机导致不可用。造成系统的所有访问,都要走数据库。
还有一种缓存雪崩的场景是:有一些被大量访问数据(热点缓存)在某一时刻大面积失效,导致对应的请求直接落到了数据库上。
举个例子 :秒杀开始 12 个小时之前,我们统一存放了一批商品到 Redis 中,设置的缓存过期时间也是 12 个小时,那么秒杀开始的时候,这些秒杀的商品的访问直接就失效了。导致的情况就是,相应的请求直接就落到了数据库上,就像雪崩一样可怕。
那在微服务中,雪崩指的是什么呢?我们先来看看这个问题。
微服务中的雪崩指的是什么?
微服务架构下,系统被拆分成了很多微服务(比如电商系统可能分为用户服务、商品服务、订单服务等服务),这些微服务协同工作对外提供服务,一个用户请求可能会需要多个服务参与。
在没有任何措施的情况下,如果某个服务调用出现了异常(比如请求的响应时间变长),那就会波及到调用这个服务的所有相关服务,从而引起了一系列连锁反应,最终导致 整个服务链路崩溃 ,这就是 微服务中的雪崩 。
很多小伙伴估计要说了,微服务之间进行调用(RPC 或者 HTTP)的时候,一般会有 超时和重试机制 来确保服务的成功执行,是不会整个服务链路崩溃出现这种问题的。这样想的话,那就有问题了。超时和重试机制很实用,但微服务下 仅仅有超时重试机制是不行的,高并发场景下,依然可能有大量请求挤压的问题发生。
举个例子:一个用户请求需要经过服务 1、服务 2、服务 3 和服务 4。假如服务 2 的调用出现异常,导致需要 10 秒才能返回响应,这就必然会导致 10 秒内该请求线程会一直处于阻塞状态。
随着时间的推移,如果系统收到的请求越来越多的话,会导致大量请求阻塞等待积压在服务 1 和服务 2,直接导致连接池爆满,系统负载过高,最终导致服务 1 和服务 2 崩溃。
由于微服务中的服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。随着时间推移,依赖于服务 1 和服务 2 的服务最终也会变得不可用,形成级联失败,最终导致整个服务链路崩溃。
高并发场景下,这种情况是绝对不允许出现的,后果极其严重。出现这种问题,至少也是生产环境 P0 级事故,年终奖什么的就不要想了。
那导致微服务中的雪崩问题的常见原因有哪些呢?接下来,我们来简单总结一下。