浅谈千亿级系统系列之三:负载均衡(干到开裂的干货篇)

Posted 张宇Station

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈千亿级系统系列之三:负载均衡(干到开裂的干货篇)相关的知识,希望对你有一定的参考价值。

点击标题下「张宇Station」可快速关注

Hello大家好,欢迎来到第三弹。


前面两期我们在轮廓上说了好多大型系统和其他系统的区别,这次来点硬核干货。 


负载均衡作为尽人皆知的系统设计基本概念,每次面试象征性的必然会说一句: “嗯这里需要加一个load balancer”。


然鹅并不是每个人都清楚到底怎么做,这篇我们就深入一把,本文节奏较快,系好安全带。



接着上一篇的例子,我们的视频分享应用,假设我们要把上传的视频发送给一坨服务器进行编码压缩,怎么保证这些服务器都均匀收到请求,来避免某些机器过热而另一些机器太闲呢?


先明确一个基本问题,当人们说负载均衡的时候,负载到底指的什么?每个系统不一样,绝大多数情况就是内存,CPU和IO。


内存又和CPU/IO不太一样,内存是绝对的硬通货,一旦不够马上崩溃,CPU和IO是分享型资源,不够的时候大家轮着用,大不了大家一起慢,但不会全军覆没。


然鹅,在实战中,CPU/IO也同样重要,因为一旦大家都变慢,对于繁忙的系统来说,就意味着被占用的内存不能即使释放,或者队列中等待的任务不能即时被清空,最后还是一样的下场:内存不够而全盘崩溃。


所以,内存最致命,CPU/IO也不可小觑。


好,明确了目标,先从基本的开始:纯随机或者轮盘策略即可满足95%的系统需求


这也是为什么之前提到尽管大家都知道LB,但是并不每个人都具体了解,因为对于绝大部分的系统来说,发送请求的时候随机挑一个机器即可,在绝大多数情况下能保证每台机器得到均匀使用,而且不受发送方/接收方机器数量限制。


但这种策略有两个主要问题:


  • 1. 当量级增大的时候,集群中难免会有不同等级的服务器,有的贵有的便宜,贵的可一次处理500个请求,便宜的只能处理100个。纯随机必然会浪费高级机器,参见木桶原理。


  • 2. 如果每个请求需要的资源不一样,有的视频较长有的较短,对服务器端的资源占用也不一样,而且难以预测。在少数情况下,会有连续几个较大请求落到同一台机器的可能性。如果对系统可靠性要求较高的话,这个概率其实并不低。


尽管问题多多,可为什么说还是可以满足95%的需要呢,因为大部分的中小型系统往往都有过量的资源,也就是说你那点请求根本用不着你那五六台机器,大部分时候资源占用量都在20%以下,所以在这个量级,随便一点智障算法都够用。


浅谈千亿级系统系列之三:负载均衡(干到开裂的干货篇)


当系统庞大之后,性能就变得及其重要,如果一万台机器的资源占用量天天都在20%上下,老板肯定掀桌子,负载均衡要解决的核心问题就是如何能让一万台机器天天保持在85%的资源占用率上还能不崩溃。


说到了资源占用率和掀桌子的问题,插一句,这个话题会在下一篇“第四弹:性能与资源”中祥述。


另一种常见策略是:挑请求数量最少的服务器发送


意思是记住给每个服务器发送请求的数量,从数量上保证公平。这样的好处是可以给高性能机器多分一些配额,可以解决上面第一个问题,可还是不能解决第二个问题,因为理论上讲每个请求对资源的需求程度不可完全预测。


这个策略还引入了一个麻烦的问题,就是严重受发送方机器数量绑定,如果明天我们要增加发送方的机器数量,系统要能自动检测到这个变化然后每人自己降低配额,从代码上可以实现,但是one more thing to break。


退一步如果想手动调整,就会面临先降配额还是先加机器的两难处境,先加机器就会超载系统,先降配额就会阻塞用户请求,长远来看还极大增加系统了的维护成本。


下一个显而易见的策略是:那就挑最清闲的机器发送啊


相比于上一个策略,这个完美解决了机器性能不等,和每个请求大小不一的隐患问题,而且还不受发送方机器数量绑定,因为每台发送方相对独立,加减机器都不受影响。


看起来不错,但也有问题。


首先,你怎么知道哪台机器最清闲。一般都是要间歇性发个请求给每台机器问一下,然后再排个序。假设接收方有万台机器,这个操作很费油,而且很慢。一慢就不准,一费油你就要考虑降低频率,就更不准了。


第二,加入发送方有万台机器,然后某台可怜的服务器恰好比较闲,结果被数万个请求一起瞄准,就会进入:”崩溃->重启->刚起来看起来比较闲->被瞄准->崩溃“ 的无限循环。


浅谈千亿级系统系列之三:负载均衡(干到开裂的干货篇)


其实这个策略已经很好了,只需要一点点改进:随机二选一


随机二选一的意思是每次从万台服务器中随机挑两台,然后把请求发给那个两者中相对清闲的那个。96年的时候由哈佛一个博士生在毕业论文中提出,现在在业界广泛使用,而且在实战中效果出奇的好。


说到这里,有人要问了,为什么不用专门的Load Balancer?


老问题,老答案,对于一般系统完全可以。但是缺点在于:a) 增加延迟,b) 有可能因为这个集群本身的问题而导致整个系统不能用,c) 如果集群有多个节点,挑哪个节点又成了问题。


继续我们的随机二选一,它也不是完全没有问题,对于每台机器清闲程度的追踪往往是异步的,越异步越不准。所以很多决定都是基于N秒之前的信息决定的,即刻舟求剑。


所以为了进一步完善,有的系统就在服务器端又加一层检测,即“收到一个请求的时候如果我太忙了就退回去”,然后发送方再换人重试,这个策略在实战中也屡试不爽,有奇效。


然鹅,上面所有的策略都忽略了一个问题,就是资源的延迟生效性,即“我现在清闲不太表我一会也清闲”。很多时候大量的内存占用都是在请求进行到一半的时候才开始的,这时候就没什么好办法了,饭都盛到碗里了,撑死也得吃完,结果有的机器就撑死了。


每一个系统都有自己独特的需求,有的关系延迟有的关心稳定性有的关心吞吐量,上面提到的几个策略只是几个选项而已,很多时候并不用这么复杂, 更多是鱼和熊掌不可兼得,这也是系统设计的真谛。


下期我们深入说说性能和资源管理,敬请期待。 




关注我





以上是关于浅谈千亿级系统系列之三:负载均衡(干到开裂的干货篇)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud系列之三---Ribbon负载均衡使用

如何搭建应对亿级流量的高可用负载均衡?

亿级Web系统负载均衡几种实现方式

讲讲亿级PV的负载均衡架构!

(转)详解LVS负载均衡之三种工作模型原理和10种调度算法

爆赞!千亿级Mysql数据迁移mongodb成本节省及性能优化实践