한 컴퓨터에서 여러 컴퓨터로 데이터를 빠르게 복사하는 방법

한 컴퓨터에서 여러 컴퓨터로 데이터를 빠르게 복사하는 방법

아래와 같이 작업 흐름에서 몇 가지 병목 현상을 발견했습니다. 다른 노드 컴퓨터로 데이터를 보내야 하는 마스터 컴퓨터가 있습니다. 이는 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개의 노드를 생성할 수 있습니다. 그런 다음 스크립트를 실행하고 시퀀스 복사본과 비교합니다(스크립트에 제공된 표준 방법). 하나의 시스템/하드 드라이브에서만 작업하더라도 속도가 더 빠릅니다(따라서 대표성이 없음).node0master

#!/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동시에 여러 명령을 실행합니다 .

다른 사람과 프로세스가 시스템에 액세스해야 하기 때문에 대역폭이 완전히 포화되지 않도록 실행기 수를 조정하십시오.

관련 정보