아래와 같이 작업 흐름에서 몇 가지 병목 현상을 발견했습니다. 다른 노드 컴퓨터로 데이터를 보내야 하는 마스터 컴퓨터가 있습니다. 이는 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개의 노드를 생성할 수 있습니다. 그런 다음 스크립트를 실행하고 시퀀스 복사본과 비교합니다(스크립트에 제공된 표준 방법). 하나의 시스템/하드 드라이브에서만 작업하더라도 속도가 더 빠릅니다(따라서 대표성이 없음).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
동시에 여러 명령을 실행합니다 .
다른 사람과 프로세스가 시스템에 액세스해야 하기 때문에 대역폭이 완전히 포화되지 않도록 실행기 수를 조정하십시오.