【性能优化】9.1 [集群] 计算与数据分布
9.1 计算与数据分布
数据量很大时,可以采用多台机器来分担计算任务,也就是集群。参与计算的机器称为分机,通常还会有个控制程序,负责管理分配各分机的计算任务并汇总计算结果,称为主机。
分机一般都会对应一个物理机器,逻辑机器起不到分担计算量的作用。而主机主要负责控制,实际承担的计算量并不大,很可能是个逻辑机器,可以由某个分机线程充当,或者由集群外的应用程序来充当。
多机并行和单机上的多线程并行类似,只是把分配给线程的任务改为分配给分机。
SPL 的 fork 语句也可以支持多机并行,需要事先在每个分机上启动集算服务器并配置好访问地址。
A |
B |
|
1 |
["192.168.0.101:8281","192.168.0.102:8281",…, "192.168.0.104:8281"] |
|
2 |
fork to(4);A1 |
=file("orders.ctx").open().cursor(area,amount) |
3 |
return B2.groups(area;sum(amount):amount) |
|
4 |
=A2.conj().groups(area;sum(amount)) |
一年的订单表很大,按季度分成四份分别存在 4 台分机上,在每个分机中都用相同的文件名命名(内容不一样)。A1 是这 4 台分机的访问地址(以后就用最后一节地址来表示分机)。A2 的 fork 语句把其代码块发送到分机上的集算器去执行,每个分机执行完之后会把返回值传送到主机,主机收集到所有分机的返回值再继续向下执行,完成最后的汇总。
分机还可以使用多路游标进行并行计算:
A |
B |
|
1 |
["192.168.0.101:8281","192.168.0.102:8281",…, "192.168.0.104:8281"] |
|
2 |
fork to(4);A1 |
=file("orders.ctx").open().cursor@m(area,amount;;4) |
3 |
return B2.groups(area;sum(amount):amount) |
|
4 |
=A2.conj().groups(area;sum(amount)) |
这样就可以利用多台机器来分担计算任务,提高计算性能。
一般来讲,一个集群中各个分机的物理配置是相同的,运算能力是基本相同。上面这个例子中,一年的数据分成4个季度放到4台分机上,可以认为是相对平均的,这样每个分机遍历的数据量差不多,没有某个分机的任务过重导致其它分机要等待的状况。
如果我们把问题改一下,先按指定时间段做过滤后再分组汇总,情况就不太一样了。
假定要作为过滤条件的时间段在第一季度之内,再假定数据是按日期有序的(这是经常可满足的),满足条件的记录可以利用数据有序被迅速定位,这样,102、103、104 分机也会迅速发现自己并没有什么事要做,几乎所有任务都压在 101 分机上了。
如果采用蛇形分布方式就可以避免这个问题。假定每天的数据量差别不大,我们用数据的日期除以 4 的余数来决定其分布的分机,1 号、5 号、9 号、…的数据放在 101 分机;2 号、6 号、…的数据在 102 分机;…;4 号、8 号、…的数据在 104 分机。这时候再执行刚才的任务,就不会发生任务严重不平衡的状况了。
理论上,这又会造成新的不平衡,比如我们要对日期是 1 号、5 号、…的数据进行统计时,任务又会全落到 101 分机上,但实际业务中几乎不会有这种计算需求。对于大多数应用场景来说,蛇形分布要优于顺序分布。
合理的数据分布方案要根据计算目标来设计,不存在能适应一切运算的方案。