这个问题不是具体的语言问题,而是思路的问题.主要提供一种程序快速解决的思路.
已经有这样一个列表.大量的数据.
APP | shard | Port | Mem | HostName | newHost |
---|---|---|---|---|---|
app1 | 0 | 8804 | 1G | a.b.c.d | |
app1 | 1 | 8805 | 1G | a.b.c.e |
情况如下:
1. 同一个app有不同的shard数量.
2. Port有可能有重复的.
3. 内存不固定有很大的30G也有很小的不足1G(不足1G按1G计算,已经处理过)
需求: 要将这些内容迁移到新的一批服务器上(新的服务器内存大,机器少.).
1. 有一个全新的机器列表.每台最大可以使用64G内存.
2. 同一个app分布到不同的服务器上.
3. 不能让port有冲突.像相同的一个port最多有达到20条记录.
4. 要合理分布.
最后输出,每条记录对应的新服务器列表.
想用个程序计算出来,有没有比较简单的办法,记录太多,手工去做太麻烦了.
根据@airy的思路,写了一个awk版本的,因为简单.
#!/bin/bash
awk -v file=new.host -v i=0 -v pianyi=0 'BEGIN{
OFS="\t"
while ((getline < file ) > 0 ){
redis[i]=$1
i++
}
}{
do
{
num=NR%i+pianyi
if ($4 <= 64-mem[redis[num]] ) {
if (redis[num]" "$3 in port){
pianyi++
}else{
mem[redis[num]]+=$4
port[redis[num]" "$3]++
print $1,$2,$3,$4,$5,$6,$7,$8,redis[num]
pianyi=0
}
}else{
pianyi++
}
}while(pianyi != 0)
pianyi=0
}' re.list
PS:re.list是已经按内存大小排序后的列表.
反向检查,是否分配合理:
bash get_table.sh | awk '{to[$NF]+=$4;port[$NF" "$3]++}END{for(x in to){print x,to[x]};for(y in port){print port[y],y}}'
我理解的需求:
1.现在有N个App,Mem占用从30G到1G不等,各自占用1个端口;
2.将这些App分配到N台64G Mem 的机器上,端口不能重复使用。
一种思路:
将所以 App 按 Mem 倒序排列
1. 取 Mem 占用最大的 App N;
2. if (N.Mem == 64) { 给 N 分配一台机器,将 N 从列表中移除。去步骤 1 }
3. if (N.Mem < 64) { 遍历 N 下面的所有机器,找 M 使 M 满足 M.Mem < 64-N.Mem 且 M.Port != N.Port 将 N,M放到一台机器,移除M,N。如果M.Mem + N.Mem < 64.重复找M, 去步骤1.}
简单来说:先找占用 Mem 最大的 App,然后找哪些 App 可以跟他放在一起(端口不重复),直到尽可能多的占满 64G 。依次循环,直到所有 App 都找到机器。