聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

Erlang公平调度的误解

2014-04-27 18:25 浏览: 7662 次 我要评论(0 条) 字号:

本文链接地址: Erlang公平调度的误解

Erlang公平调度是它的哲学(或者说坚持)之一,从第一个版本的beam代码的时间片分配和抢占开始,到最近版本的bif对公平性的坚持(比如R17版binary_to_term就大幅做了修改,代码复杂很多,执行效率也有下降,但是在碰到大的binary的情况下,通过Trap机制会让出执行权,排队后再回来断点续作), nif(加入扣除时间片的接口),这些努力保证了erlang系统是个公平的系统。

很多终端系统和业务会受益于这个哲学,如云计算。不管用户大小和业务的负载情况如何,系统性的公平性可以保证每个用户有机会被服务,对用户有很好的体验。 而公平性一定是要贯穿于整个系统里面,特别是有设计哲学方面来保证,每个模块和系统的设计者都能心有默契来遵守。如果有一个人打破了,整个系统其他的公平也就失去意义。这也是为什么公平性这么难做的核心原因。

我们在云业务里面会经常碰到一个系统在服务内部用户的时候效果很好,针对公众服务的时候就遇到各种抱怨。我举个简单的例子如RDS(mysql云),如果不考虑公平性,来一个SQL服务一个,而不管SQL的大小和复杂度,就会马上面临一个问题,强势的几个用户会把这个系统的资源全部占光,其他用户的SQL根本没有机会得到执行。这个问题当然可以通过mysql后端的资源隔离,如cgroup限制CPU,内存,IO,网络的消耗,还需要通过精确的每条SQL的消耗来在适当的时候让出控制器来达到目的。 这个链条上的公平非常难做,所以说大部分的系统都是蹩脚的,无法做到真正的公平,只是程度的差别而已。

虽然Erlang骨子里面就强调公平,而且在身体力行,但是实现上的细节决定了,下面几件事情上做不到公平,留下了坑。我们知道erlang代码核心的思路是根据规约数(函数执行一个,算一个规约),每个进程预先分配比如2000个时间片。时间片用完或者条件不满足(比如需要等消息)时候让出控制权,而且系统是消息驱动的。

VM就是个超大的循环,基本上就是: 1. 拿消息 2. 执行opcode或者nif,bif 3. 收割os底层事件, 这样的结构。
其中2在努力保证公平,但是1和3在设计层面不考虑公平,有很多坑了:

1. 取消息。 erlang的消息队列是单向队列实现的,消息是按照先来后到的顺序进来的,而且消息队列是没有保护的,只要对端原因扔消息,消息就会进入队列。匹配的时候,比如有N个匹配条件,M个消息,那么计算量是N*M。在极端的情况下,如果进程的消息处理能力跟不上,马上就会出现队列爆长,然后计算量和内存激增,最终导致VM奔溃。

2. 内存的使用。任何有意义的操作都差不多需要内存,而内存是从内存分配器中取的,虽然erlang设计了非常精巧的内存分配器,每个调度器都有个自己的池。但是凡是池子,总有不满足的时候,就需要底层内存批发比如mseg_alloc或者sys_alloc,那就不可避免的用到了锁。这个锁的冲突导致的不公平就看业务模式和造化了。

3. 内部各部件的锁。 SMP的系统最不缺的就是锁了,锁的冲突几乎没法解决,用户的行为热点越高,锁也会月剧烈。虽然无锁算法在更多核的情况下,乐观的假设可能可以减少冲突,效果还是看用户。

…还有更多。这些东西都会破坏公平性,在实际的系统中会很严重,影响erlang的公平性声誉。所以最近erlang要引入dirty scheduler, native process等尝试都是为了减少这类问题造成的影响。

架构师需要更多的了解系统和业务,如果可能的话,在业务层面也需要设计成更公平的系统,从上到下和谐。

小结:世界不完美,没有绝对公平的东西。

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复