E5ee055bafa76e29c7400f02bb381e5b
漫谈分布式系统(6) -- 跑的快,也别忘了省钱

这是《漫谈分布式系统》系列的第 6 篇,预计会写 30 篇左右。欢迎订阅,听我娓娓道来。也欢迎转发朋友圈分享给更多人。

1

前面两篇分布式存储的文章讲过,存得下不够,还要存得好。存得好,主要是为了节省成本。

因为海量数据随之带来的,就是海量成本。

同样,算得快也不够,还要尽可能压榨机器计算性能,节省成本。

有别于分布式存储引擎在存储方式上做文章,由于计算逻辑优化的空间有限,并且相对属于应用层需要考虑的问题(当然,通用的优化也可以做,以后会讲),分布式计算框架更多尝试对资源的调度做优化。也就促成了一系列所谓 Resource Manager 的诞生,典型的如 Google 的 Borg 和 K8S,Apache 旗下的 YARN、Mesos,都可以归到这个大类。

2

以往,公司不同业务都会有自己专享的各种服务器和集群。这很好理解,每个业务都希望能独立运行,不受其他程序的干扰,也不留下安全隐患。

但业务负载是动态变化的,规律性的波峰波谷,不规律的业务增长和下降,随之而来的就是频繁的扩缩容。为了降低扩缩容带来的工作量和对业务的影响,一般都会留有资源余量。

所谓余量,换一个说法,就是浪费。

怎么灵活又及时地把这些浪费掉的资源利用起来,顺便减轻扩缩容带来的维护成本,就是各种资源管理器要解决的主要问题。

3

最直观的想法,就是混部。机器不再专属于某个业务,而是大家共享。我业务不忙的时候,你就可以多用点,反之亦然。这样整体利用率自然就上来了。

也就是所谓的多租户(muti tenancy)

多租户怎么共享资源呢,大家都提交任务,资源调度该怎么做呢?

最简单粗暴的是队列式的先进先出,所谓 FIFO。前面任务跑完,释放资源,后面任务才能分到资源。

显然,对多租户的支持,好处自然是整体资源率的提升,于整体有利;坏处就是牺牲了个体,失去独立性就意味着相互影响。

那怎么保证个体资源的需求呢?

4

要想保证个体的需求,只有一个办法,隔离

于是,各种资源调度系统提出了 pool、queue 一类的概念,用来在逻辑上分配资源。可以给每个 pool 设置计算资源的配额,然后只允许某一个业务使用这个 pool。嵌套和多层的 pool 又可以给业务内的隔离提供便利。

但隔离之后,资源就不能共享了,整体利用率就降下来了。

所以不能硬性隔离,只能软性隔离

于是给每个 pool 的配额是动态平衡的,支持借用和归还。

但是如果借用的份额长期不归还呢,比如被一个要跑 3 天的程序借用走了,就干等 3 天吗?

于是又支持强杀回收(preemption),抱歉,我等不了那么久,请立刻归还超出你额度的部分。为了让强杀温柔点,不至于引起大面积任务挂掉,又可以支持超出一定比例或(和)一定时间后才强杀。

强杀是后手,还可以先手。

给 pool 设置硬性的资源上限,无论别人怎么空闲,你也最多只能借用这么多。

综合到一起,就有了 Capacity Scheduler、Fair Scheduler 等各种调度器,在相互借鉴改进之后,也逐渐趋同。

  • 比如 Fair Scheduler 也支持设置权重配额,这样相对的公平才是可行的公平。

  • 比如公平策略从优先分给内存占用少的任务,改进成内存和 CPU 都考虑的 DRF(Dominant Resource Fairness) 策略。

  • 比如 Google 的 Borg 为了支持流批混部,明确支持了优先级的概念。

  • 比如工作日和周末使用不一样的分配策略,利用业务错峰来有效利用资源。

top Created with Sketch.