以下のように、ワークフローでいくつかのボトルネックが見つかりました。別のノードコンピュータにデータを送信する必要があるマスターコンピュータがあります。これは for ループで行われます。たとえば、次のようになります。
for all nodes: rsync <Options> <Master> <Node>
これは、ノード数が4つまたは8つのようにそれほど多くない場合(複製時間は約2分)、非常に効果的です。しかし、これは線形曲線です。 16ノードの場合は約3.5分かかり、128ノードの場合はすでに20分かかりました。 (ところで、この問題は私のワークフローでほとんどボトルネックになりました。)
私の意図は、愚かなループを取り除き、for all
次のことを行うことです。
1. copy master to node1
wait & check if successfull
2. copy master to node2 && copy node1 to node3
wait & check if successfull
3. copy master to node4 && copy node1 to node5 && copy node3 to node6
wait & check if successfull
...
私の質問:同様のことをするのに役立つことができるのはbashにありますか、それともより信頼性の高いソリューションがありますか? ITベースなので、ツールの使用にはいくつかの制限があります。どんな提案でも暖かく歓迎します。
私が考えたもう一つの良い点は次のとおりです。
1. copy master data to memory
2. send the memory stuff to all nodes simultaneously (if that is possible) and all nodes write simultaneously
rsync
似たようなことを処理しますか?どんなアイデアでも暖かく歓迎します。
情報提供のために、以下のように最適化できるいくつかのテストスクリプトを作成しました。たとえば、これらはノードのように扱うことができる必須でmaster
はありません。したがって、コードをさらに減らすことができます。しかし、コピーが成功したかどうかなどはまだ確認されています。 - 私が考えるものの例ですか?これをコピーし、マスターフォルダを作成し、その中にいくつかのファイルを入れて、128個のノードを作成できます。次にスクリプトを実行し、シーケンスのコピーと比較します(スクリプトで提供されている標準的な方法)。 1つのシステム/ハードドライブでのみ作業しても速度が速くなります(したがって代表性はありません)。node0
master
#!/bin/bash
#
# Tobias Holzman
# 25.03.2023
#
# Description
# Script that speeds-up the function serial copying from master to nodes
# by using other nodes at which the data are already copied.
#
# Standard Approach:
# forAll(nodes, nodei)
# {
# rsync <masterData> <nodei_path>
# }
#
#------------------------------------------------------------------------------
function copyToNode ()
{
# Simple check if folder exist
if [ ! -d $1/triSurface ]
then
echo "Error"
return 0
fi
rsync -av --progress $1/triSurface $2/ > /dev/null &
return 0
}
#------------------------------------------------------------------------------
t1=$(date +%s)
# How many nodes we have (for test purpose)
nCopy=$(ls -d node* | wc -l)
nodesEmpty=()
nodesCopied=()
copyNodes=()
# Create a string array that includes all node names
for i in $(seq 0 $nCopy)
do
nodesEmpty+=("node$i")
done
echo "We need to copy the data from master to $nCopy nodes"
echo "----------------------------------------------------"
i=0
done=0
dataAtHowManyNodes=0
while true
do
i=$((i+1))
# Copy array nodesCopied which we work with in one loop
# as we dont want to change the original array
copyNodes=("${nodesCopied[@]}")
echo ""
echo " ++ Copy run #$i"
echo " ++ Remaining nodes to which we need to copy: ${nodesEmpty[@]}"
echo " ++ Available nodes used for copy : ${nodesCopied[@]}"
echo " |-> parallel copy sequences: $dataAtHowManyNodes"
# Only master copy
if [ $dataAtHowManyNodes -eq 0 ]
then
nodeToCopy=${nodesEmpty[0]}
echo " | |-> master to $nodeToCopy"
copyToNode "master" "$nodeToCopy"
# Add node to nodesCopied
nodesCopied+=("$nodeToCopy")
# Remove node from nodesEmpty
unset nodesEmpty[0]
# Update the index
nodesEmpty=(${nodesEmpty[*]})
else
for ((j=0; j<$dataAtHowManyNodes; j++))
do
echo " |-> copy sequenz $j"
nodeToCopy=${nodesEmpty[0]}
# Master to node copy
if [ $j -eq 0 ]
then
echo " | |-> master to $nodeToCopy"
copyToNode "master" "$nodeToCopy"
# Add node to nodesCopied
nodesCopied+=("$nodeToCopy")
# Remove node from nodesEmpty
unset nodesEmpty[0]
# Update the index
nodesEmpty=(${nodesEmpty[*]})
# Node to node copy
else
nodeMaster=${copyNodes[0]}
# Remove copyNode to ensure its not used again
unset copyNodes[0]
# Update the index
copyNodes=(${copyNodes[*]})
echo " | |-> $nodeMaster to $nodeToCopy"
copyToNode "$nodeMaster" "$nodeToCopy"
# Add node to nodesCopied
nodesCopied+=("$nodeToCopy")
# Update the index
nodesCopied=(${nodesCopied[*]})
# Remove node from nodesEmpty
unset nodesEmpty[0]
# Update the index
nodesEmpty=(${nodesEmpty[*]})
fi
# Check if still remaining emptyNodes
if [ ${#nodesEmpty[@]} -eq 0 ]
then
echo " ++ Done ..."
done=1
break
fi
done
fi
wait
if [ $done -eq 1 ]
then
echo ""
break
fi
dataAtHowManyNodes=$(echo "scale=0; 2^$i" | bc)
echo " |-> Data are now on $dataAtHowManyNodes nodes"
done
t2=$(date +%s)
dt=$(echo "scale=0; ($t2 - $t1)" | bc)
t=$(echo "scale=2; $dt/60" | bc)
echo "Time = $dt s ($t min)"
#------------------------------------------------------------------------------
答え1
マルチキャストまたはブロードキャストデータフレームを使用するプログラムを見てください。これにより、すべてのファイルが一度送信されるため、プライマリサイトはネットワーク帯域幅によって制限されにくくなります。
mrsync
ここでは面白いかもしれません。しかもuftp
。
バラよりhttps://serverfault.com/questions/173358/multicast-file-transfers
答え2
ネットワークファイルシステムが利用できない場合のインストールと使用GNUパラレルrsync
同時に複数のコマンドを実行します。
他の人とプロセスがシステムにアクセスする必要があるため、帯域幅が完全に飽和しないようにランチャーの数を調整してください。