Executando processos RSync em Paralelo para Acelerar Cópias

O RSync é uma ferramenta muito útil, e extremamente flexível. Basicamente, serve para fazer cópias. Ele já salvou minha vida algumas vezes, facilitando tarefas complicadas.

Vou falar sobre algumas das características do RSync, apenas para dar uma idéia:

  • Verifica a integridade dos arquivos copiados;
  • Transfere apenas as diferenças dos arquivos (yeah, não transfere o arquivo inteiro, apenas os bits diferentes!);
  • Mantém cópias idênticas entre 2 diretórios distintos, apagando os “excessos”;
  • No caso de cópias remotas, pode usar compressão para diminuir o uso de banda;

E por aí vai …

Existem inúmeros cenários onde se pode usar o RSync. A internet está repleta de exemplos. Mas, para alguns casos, nem o Google consegue ajudar. É aí que nós, contribuidores individuais, entramos.

Mas que casos? Pensei em uns 5 agora… Mas citarei um caso particular que me deu trabalho para achar uma solução efetiva.

Antes de prosseguir, vou falar de uma particularidade do RSync. Vamos supor que você queira copiar o diretório A para o diretório B.  Antes do processo de cópia, o RSync gera uma lista dos arquivos, e quando esta lista está concluída, a cópia se inicia. Simples, não? Sem mistério. Sem problemas quando temos apenas algumas centenas de arquivos.

Mas e se tivermos alguns milhares de arquivos? E mais de 1 milhão de arquivos? Pode ser que a lista demore um bocado até ser concluída. E isso com certeza, vai consumir um monte de recursos (I/O e CPU principalmente) apenas para montar a lista. Talvez demore cerca de 1 hora até que a tarefa de cópia se inicie.

Você deve estar pensando agora:   Humm… RSync é muito lento!

Calma. Nessa vida só a morte não tem jeito. Se por acaso tem, ainda não foi divulgado para o grande público.  🙂

É aí que entram os amigos do RSync: FIND e XARGS

  • Find: Faz exatamente isso. Encontra arquivos baseado em algum critério.
  • Xargs: Pega a saída de um comando e a joga em outro comando.
Pronto. Agora é só montar o quebra cabeças. Faremos algo assim:
FIND > XARGS > RSYNC
Ok, mas como isso pode me ajudar a copiar de forma mais rápida meus 1.385.792 arquivos?
PARALELISMO!
Falei um pouco sobre isso no meu post sobre o Novo XFS. Leitura interessante se você quiser conferir.
Estória Longa Resumida
O FIND não gera uma lista de arquivos e depois exibe. Ele vai mostrando conforme encontra.
O XARGS possui diversos parâmetros, e um deles, é executar processos em paralelo.
Com isso, montamos uma linha de comando que realize este processo:
Para cada arquivo encontrado, submeto o mesmo ao XARGS, e este por sua vez, aloca uma thread de RSYNC para o arquivo encontrado.Podem ser alocadas tantas threads quantas quisermos. Mas devemos ter bom senso. A alocação vai depender da quantidade de recursos disponíveis em sua máquina. Se você saturá-la demais, no final a operação pode ficar mais lenta. Vale a máxima: Antes de colocar em produção, teste!
No meu ambiente de testes, utilizei um antigo Sun Fire V440, com 8GB RAM e 4 CPUs UltraSPARC-IIIi de 1593 MHz. O teste em si era duplicar um diretório com 80GBs de dados, distribuídos em 16.528 arquivos. Para isso criamos esta simples função, carinhosamente chamada de Parallel RSync:
function parallel_rsync()
 {
 /usr/local/bin/find $1 -type f \
 | /usr/local/bin/xargs -n1 -P8 -I% /usr/local/bin/rsync \
 --delete \
 --exclude=".snapshot" % \
 --links \
 --perms \
 --group \
 --owner \
 --devices \
 --whole-file \
 --recursive \
 $2
 }
Entendendo a Função
O “$1” é a ORIGEM, informada ao comando FIND.
O “%” é a saída do comando FIND, que o XARGS vai processar.
O “$2” é o DESTINO. O resto são apenas parâmetros do RSync, e podem ser customizados para atender a necessidades específicas. Com ela você pode montar um simples script, que invoque a função informando apenas ORIGEM e DESTINO. Alguma coisa assim:
#!/bin/bash
 parallel_rsync $1 $2
O restante vai de acordo com o gosto do freguês: tratamento de erros, geração de logs, status de saída dos processos, etc.
Mas onde está a mágica?
Observe o parâmetro “P8” do XARGS. Isso quer dizer que usamos 8 processos paralelos. Ou seja, copiamos 8 arquivos simultâneamente, ao invés do tradicional “um de cada vez“. Isso gera um grande consumo de I/O e CPU. Se fosse uma cópia remota, provavelmente iria saturar a sua rede local ou sua internet. Aqui não vale o “de grão em grão a galinha enche o papo“. Ela come todo o pacote de ração de uma só vez!  😀
O que estamos propondo aqui é paralelizar processos onde normalmente isso não seria feito. E o melhor: Usando tecnologias que já estão disponíveis, sem precisar desenvolver um programa específico para isso.
Voltando ao laboratório, fizemos testes com 4, 8 e 16 threads. Comparativamente, fizemos a cópia dos arquivos com o comando de cópia tradicional, o bom e velho “CP“. Lembrando que o CP não possui nenhuma função avançada, como por exemplo garantir a integridade dos arquivos ou copiar somente as diferenças.
Após a conclusão dos testes, obtivemos estes tempos:
04 Processos paralelos
real    53m55.795s
user    41m59.123s
sys     42m29.469s
08 Processos paralelos
real    48m41.182s
user    42m5.733s
sys     44m21.928s
16 Processos paralelos
real    47m36.563s
user    40m31.918s
sys     43m35.772s
E com o tradicional CP
real    53m30.625s
user    0m2.007s
sys     10m42.787s
Update
Tive a oportunidade de testar este processo em um M4000, que possui processadores de 2.53 GHz e 16Gb RAM. O volume de dados processado foi o mesmo (80GBs distribuídos em 16.528 arquivos). O tempo de cópia com “CP” foi de 37 minutos. Mas com o Parallel RSync, apenas 23 minutos. Nada mal!
Enquanto o Parallel RSync estiver em execução, podemos usar o comando prstat (ou top) para ver a lista de processos. Teremos um cenário parecido com este:
PRSTAT RSYNC
O comando ps também mostra uma perspectiva interessante:
PS RSYNC
Conclusão
Analisando os resultados, percebemos que vale a pena usar o RSync paralelizado. Teremos um tempo de cópia menor, e a garantia de que todos os arquivos armazenados estarão íntegros. Isso o CP não tem como garantir. Nem mesmo o SCP (cópias remotas).
Ou seja: Onde houver necessidade de realizar com segurança e integridade uma cópia, um backup ou manter sites sincronizados, Parallel RSync neles!
Ah, em caso de problemas de implementação desta dica, comece observando se o seu sistema possui estes aplicativos instalados, com estas versões (as mais recentes também servem):
– rsync version 3.0.9 protocol version 30
– xargs (GNU findutils) 4.4.2
– find (GNU findutils) 4.4.2
Um abraço a todos, e até a próxima!

3 thoughts on “Executando processos RSync em Paralelo para Acelerar Cópias

  1. Ola Andre,

    Muito bom seu artigo!
    Estou querendo implementar na copia de Maildir, sera que consigo mandar os diretorios ?
    Porque da forma que esta copia todos os arquivos de uma pasta para a outra ! Nao cria os diretorios ! Uma abraco

    • Obrigado pelos comentários!
      Respondendo a pergunta: Você pode copiar aquivos com full path também. Basta alterar um pouco as flags do rsync. Pelo que entendi, acredito que você esteja precisando copiar o Maildir de um servidor para outro.
      Vamos supor que você tenha um arquivo texto chamado “FILES.TXT“, e que seu conteúdo seja a lista dos arquivos/diretórios que deseja copiar.
      Exemplo: “/home/moreni/Maildir”. Basta montar uma estrutura de repetição, como esta:

      for FILES in `cat "FILES.TXT"`
      do
      rsync \
      -IRcauzHt \
      --progress \
      root@IP_SERVIDOR_REMOTO:$FILES / >> $Log 2> $Log.err
      done

      Observe os flags usados no rsync, bem como o parâmetro “/” na penúltima linha. Os flags ajustam o rsync de forma a copiar diretórios com full path, e o parâmetro “/” é o local para onde os arquivos serão descarregados. Aí está o segredo.
      Espero ter ajudado.
      Um abraço.

  2. Olá Andre,

    Muito obrigado pelo retorno
    É isso mesmo backup de maildir com muitos arquitos preservando o full path.
    Ex:

    email_teste/Maildir/cur/ (Emails)
    email_teste/Maildir/.Sent/ (Emails)

    E por ai vai !!!!!
    Com a primeira opção estava copiando apenas os arquivos e nao criava os diretorios Maildir cur .Sent e etc !!!

    Essa opção que vc mandou quem faz o paralelo não é o xargs usando P8 ?

    Nesse for não tem o xargs !!!!

Leave a Reply