系统设计基础4:分布式速率限制
前面的文章介绍了系统的水平扩展、负载均衡等概念,采用负载均衡的方式,可以提高系统的可用性,在某一服务器出现故障时,可以将请求发送到其他服务器,保证系统的正常运行。本文会继续讨论当请求量超过服务器的处理能力时的各种问题和解决方案。
级联失败
问题描述
假设目前有服务器的数量为4,请求有400个,每台服务器平均处理100个请求。此时服务器0出现故障下线,按照负载均衡的策略,原本由服务器0处理的100个请求均分到其他三台服务器,每台服务器平均处理133个请求。
4台服务器各处理100个请求 Server0崩溃,其他服务器处理133个请求但是,服务器1的最大处理能力就是100,此时处理133个请求使得服务器1崩溃了。再次按照负载均衡的策略,其余两台服务器各处理200个请求。如果其余两台服务器无法处理200个请求的话,会导致所有的服务器最终都停止服务。
Server1崩溃,其他服务器处理200个请求由于采用负载均衡的策略,当服务器数量减少时,使得其他服务器的请求量增加,超过了服务器能处理的最大能力,最终导致所有服务器都停止服务,称为级联失败。
解决方案
在每个服务器内部,实现一个固定长度的队列,这个队列的长度即为服务器的最大处理能力。如下图所示,如果服务器0的最多能处理的QPS为100,那么设置队列的长度为100。当队列已经满时,新来的请求会返回失败。
服务器的队列通过这种方式,当服务器数据减少时,如果其他服务器有剩余的处理能力,这些请求会发送到其他服务器上并处理;如果处理能力不足,也不会导致其他服务器因为负载过大而崩溃。
此时返回的失败,应该提示客户端是由于负载过大导致,客户端在得到此信息后,可以在一定时间后重试。
降低服务器负载的方式
以下再简要的讨论几种能够降级服务器负载的方式
自动扩容
当已知请求量可能会暴涨时,可以提前增加服务器的数量以应对。但如果是突发情况,自动扩容是一种很好的解决方案,能及时应对突增的请求量。通常的云上服务器都提供类似的功能。
批量处理
假设我们要将一封邮件发送给公司的每个员工,如果员工数量很多,发送时的系统的持续负载会很大。此时可以将员工进行分组,比如1000个一组,每组员工发送一封邮件,就可以大幅降低持续负载的时间。
预估统计
社交网站上会展示每个帖子的转发数、评论数或者点赞数等。如果是一个公众人物,他的帖子的访问量很大,各种指标的请求量也很大。此时可以提供一个预估结果,避免直接请求数据库,降低每次请求的负载。
使用缓存
使用缓存将之前请求过的返回保存下来,后续相同的请求可以直接返回缓存的结果,降低系统负载。但缓存是一把双刃剑,将一些敏感信息放在缓存中可能是不安全的,因此在使用的时候需要注意场景,比如用户头像等信息放在缓存中是合适的。
小结
本文针对在某服务器崩溃时,如何避免其他服务器也出现级联崩溃的问题,介绍了使用队列进行分布式速度限制的方式。此外还介绍了其他几种能够降级服务器负载的方式。如果你知道其他好的方式,欢迎在评论区留言分享。
欢迎大家订阅专题,其中包含了系统设计基础系列的全部文章:System Design