1. 介绍
常见的Load balance算法想必大家都不陌生,Random、Round-robin、Least connection、Consistent hash等应该都耳熟能详,这些算法都在实践中有广泛的应用,例如Nginx、Haproxy等负载均衡模块都有相应算法的实现。本文将和大家分享一种全新的Load balance算法:Power of Two Random Choices[1],也算是Fast 2019 best paper解读《Distcache: Provable load balancing for large-scale storage systems with distributed caching》 的续篇,DistCache利用Power of two random choices实现Cache Query的Load balance:就是在查询Cache中item的时候,从命中的2个Cache节点中选择负载较低的Cache节点来服务;实现简单,效果却不简单。除此之外,新版本的Nginx和Haproxy近都增加了对Power of Two Random Choices算法的支持[8、9],可见一斑。
本文将从Power of Two Random Choices算法的起源说起(也就是数学里面经典的Balls into Bins问题[4、5]),向大家展示Power of Two Random Choices算法背后的数学原理。并介绍其在解决Hash冲突中的应用,想必能进一步加深大家对Cuckoo Hash、BloomFilter等使用多个hash function做法的理解。
2. Balls into Bins
首先看数学一个经典的Balls into Bins问题[4]:
假如顺序地将n个Balls投入到n个bins(垃圾桶),策略是从n个bin中随机独立均匀地选择任意一个bin
那么当抛球结束的时候,以非常高的概率( 也就是以概率1-o(1)
),n个bin中大负载为(1+o(1))logn/loglogn
个balls。注意o(1)
指的是高阶无穷小,可以直接忽略掉。
这实际上就是一个无状态的Load balance问题,考虑一个负载均衡器(LB)将n个请求随机等概率的发送给n个Server,那么就可以知道Server上大的可能负载会是多少。
3. Power of two random choices
如果选择上做一个小改动,也就是今天要说的Power of two random choices[1]:
假如顺序地将n个Balls投入到n个bins(垃圾桶),策略是从n个bin中随机独立均匀地选择d个bin,然后选择Ball少的bin放入
那么当抛球结束的时候,将以非常高的概率( 也就是以概率1-o(1)
),n个bin中大负载为(1+o(1))loglogn/logd+O(1)
个balls。
现在情况Balls的数量往往远大于Bins的数量,所以扩展一下[5]:
假如顺序地将m个Balls投入到n个bins(垃圾桶),策略是从n个bin中随机独立均匀地选择d个bin,然后选择Ball少的bin放入,其中m>=n,d>=2
下面给出一个一组计算的算例,分别m=n={2^2,2^3,2^4......,2^64},其中红色为普通的Balls into Bins问题的大负载,蓝色为Power of two random choices d=2情况下的大负载:
通过上图可以发现,Power of two random choices负载均衡的效果是不错的。尽管上面的模型太过理想,假定了所有的key都是必须均匀分布,每个request的size都是相同,和实际生产环境相差巨大,但仍然不妨碍我们认定这种做法的有效性。
4. App
(1)Load balance
得益于Power of Two Random Choices的实现简单和效果良好,开源的NGINX在版本1.15.1中开始支持[8],Haproxy也在2.0版本中开始支持,且将其替换成了默认的随机算法[9],文献[9]中Haproxy有一些对比测试,大家可以参考。
(2)Hash
如果使用这种方法来解决Hash冲突,以开链(separate chaining)法为例,如果每次选择哈希映射的桶时,通过两个hash function随机挑出两个桶,并从中选择链表长度相对更短的桶插入[10](如下图),根据Power of Two Rand Choices理论,那么每个hash bucket的开链长度肯定会更加均衡。
实际上回过头来看Cuckoo Hash、BloomFilter设计多个hash function是有道理的。
如上图,是一个Cuckoo Hash一种典型实现,通过两个hash函数来映射key,且每个bucket都可以存放多个items,实际上根据Power of Two Random Choices的原理,这样,可以使得每个bucket的冲突更加均衡,从而可以在设计Cuckoo hash的时候设置较小的Bucket容量,避免空间浪费,或者换一个角度,可以延迟resize hash的发生。
5. Summary
Power of two random choices尽管是一种理想的理论模型,但是方法和思路仍然可以作为生产实践的指导,这也大概是理论研究的意义所在。
(需要特别声明的是,限于本人是个数学渣渣,所以第2、3小节数学分析大家悠着点看,有任何错误的地方,轻喷)。
鸣谢
非常感谢 @林谨 对文章[6]中存在问题的指出,让学习到了两个非常有意思东西:(1)Small cache, big effect[7];(2)Power of two random choices[1]。关于Fast2019 DistCache更深入的解读可以参考 @林谨 的博文[2],娓娓道来,非常深入,值得拥有。
Notes
限于作者水平,难免在理解和描述上有疏漏或者错误的地方,欢迎共同交流;部分参考已经在正文和参考文献列表中注明,但仍有可能有疏漏的地方,有任何侵权或者不明确的地方,欢迎指出,必定及时更正或者删除;文章供于学习交流,转载注明出处
参考
[1]. Mitzenmacher M. The power of two choices in randomized load balancing[J]. IEEE Transactions on Parallel and Distributed Systems, 2001, 12(10): 1094-1104.
[2]. FAST 2019 DistCache. https://jimchenglin.github.io/2019/04/15/FAST-2019-DistCache/
[3]. [1]. Liu Z, Bai Z, Liu Z, et al. Distcache: Provable load balancing for large-scale storage systems with distributed caching[C]//17th {USENIX} Conference on File and Storage Technologies ({FAST} 19). 2019: 143-157.
[4]. 皇甫先鹏, 罗雪山. 基于非对称 balls-into-bins 的高效平衡负载分配模型[J]. 国防科技大学学报, 2013, 35(3): 67-71.
[5]. Balls into bins problem. https://en.wikipedia.org/wiki/Balls_into_bins_problem
[6]. Load balancing for large-scale storage systems. https://zhuanlan.zhihu.com/p/64265624
[7]. Fan B, Lim H, Andersen D G, et al. Small cache, big effect: Provable load balancing for randomly partitioned cluster services[C]//Proceedings of the 2nd ACM Symposium on Cloud Computing. ACM, 2011: 23.
[8]. NGINX and the “Power of Two Choices” Load-Balancing Algorithm. https://www.nginx.com/blog/nginx-power-of-two-choices-load-balancing-algorithm/
[9]. Test Driving “Power of Two Random Choices” Load Balancing. https://www.haproxy.com/blog/power-of-two-load-balancing/
[10]. 随机的力量(1) - The power of random two choices. https://blog.csdn.net/three_body/article/details/49538777