Sumário
Como você pode configurar o Linux para ler de um disco / sistema de arquivos local e gravar em um compartilhamento de rede ao mesmo tempo, em vez de ler enquanto nenhum dado estiver passando pela rede e enviá-lo pela rede enquanto o disco local estiver ocioso?
É muito mais rápido ler e escrever ao mesmo tempo, em vez de executar apenas uma operação e depois a outra de maneira alternada.
Detalhes
Estou movendo uma grande quantidade de dados de discos locais em uma máquina Linux para um dispositivo NAS.
Estou usando rsync
para copiar basicamente /srv/data
para /mnt/nas
, que é uma montagem CIFS.
Começou bem, lendo a 100 MB / s e gravando no NAS a 100 MB / s (limite de rede de gigabit), com a leitura e a gravação acontecendo simultaneamente.
No entanto, agora, algumas horas depois, estou descobrindo que está lendo no disco local, interrompendo a leitura enquanto grava no NAS e, quando não há mais dados para gravar no NAS, ele retoma a leitura do disco novamente. A rede está ociosa enquanto o disco está sendo lido e o disco está ocioso enquanto a rede está em uso.
Escusado será dizer que ler 200MB e depois escrever 200MB leva muito mais tempo do que ler e escrever esses 200MB ao mesmo tempo.
Como posso configurar o kernel de forma a manter o comportamento anterior de ler e escrever ao mesmo tempo, em vez de alternar entre ler e escrever, executando apenas uma operação por vez?
Algumas observações: quando o disco local lê a 100 + MB / s, tudo parece acontecer paralelamente, mas depois que o disco fica mais lento (parece que agora está com apenas 20 MB / s por algum motivo), é quando ocorre a leitura / gravação. mudança parece acontecer.
Também posso executar sync
manualmente a cada poucos segundos para que as gravações ocorram em paralelo com as leituras (embora obviamente a velocidades reduzidas), colocando sync
um while
loop para que seja executado a cada cinco segundos não parece a solução certa ...
O kernel parece armazenar em cache cerca de 1 GB de dados e depois gravá-los na rede o mais rápido possível - o que é bom - só não entendo por que o disco lento precisa parar de ser lido enquanto os dados são enviados pelo rede.
Respostas:
Após mais algumas investigações, parece que esse problema está menos relacionado ao kernel e mais sobre como o
rsync
CIFS interage.Pelo que sei, o que está acontecendo é que, quando
rsync
fecha o arquivo de destino, o CIFS (e provavelmente qualquer sistema de arquivos de rede) garante que o arquivo seja completamente liberado e gravado no disco remoto antes que oclose
syscall retorne. Isso é para garantir a qualquer aplicativo que, uma vez que a operação de fechamento seja concluída com êxito, o arquivo tenha sido completamente salvo e não haja risco de erros adicionais que possam causar perda de dados.Se isso não fosse feito, seria possível que um aplicativo fechasse um arquivo, saia pensando que a operação de salvamento foi bem-sucedida e, posteriormente (talvez devido a um problema de rede) os dados não pudessem ser gravados, afinal, até então é tarde demais para o aplicativo fazer algo a respeito, como perguntar ao usuário se ele deseja salvar o arquivo em outro lugar.
Esse requisito significa que toda vez que a
rsync
cópia de um arquivo é concluída, todo o buffer de disco deve esvaziar a rede antes quersync
seja permitido continuar lendo o próximo arquivo.Uma solução alternativa é montar o compartilhamento CIFS com a opção
cache=none
que desativa esse recurso e faz com que todas as E / S sejam direcionadas diretamente ao servidor. Isso elimina o problema e permite que leituras e gravações sejam executadas em paralelo, no entanto, uma desvantagem dessa solução é que o desempenho é um pouco menor. No meu caso, a velocidade de transferência da rede cai de 110 MB / s para 80 MB / s.Isso pode significar que, se você estiver copiando arquivos grandes, o desempenho poderá ser melhor com o comportamento alternativo de leitura / gravação. Com muitos arquivos menores, desabilitar o cache resultará em menos descargas de cache cada vez que um arquivo for fechado, para que o desempenho possa aumentar lá.
Parece
rsync
precisar de uma opção para fechar seus identificadores de arquivo em outro segmento, para que ele possa começar a ler o próximo arquivo enquanto o último ainda estiver sendo liberado.EDIT: Confirmei que
cache=none
definitivamente ajuda a transferir muitos arquivos pequenos (traz de 10 MB / s até 80 MB / s), mas ao transferir arquivos grandes (1 GB ou mais)cache=none
reduz a transferência de 110 MB / s para os mesmos 80 MB / s. Isso sugere que a transferência lenta de muitos arquivos pequenos tem menos a ver com a procura do disco de origem e mais com tantas liberações de cache de todos os arquivos pequenos.fonte
rsync
não ler o arquivo em um segmento diferente (na verdade, processo diferente), porque ele é projetado para que uma cópiarsync
está em execução em cada lado da rede, embora no seu caso ambas as cópias estão do mesmo lado (e o sistema de arquivos está escondendo o fato de que existe uma rede). Eu acho que não ajuda, porque o processo do leitor enche muito rapidamente o cano enquanto o processo do gravador está bloqueando umclose()
.rsync
teria melhor desempenho se você estivesse usandorsync
o fio, não o CIFS.rsync
no NAS seria usarrsync
através da rede (comorsync -a files localhost:/dest/path
), introduzindo artificialmente um enorme buffer (como, pelo menos, múltiplos megabytes, pelo menos) nas conexões de rede. Não sei como seria o melhor truque para fazer isso.rsync
na própria caixa NAS também resolva o problema. Um pouco mais complexo (permissões estranhas do NAS, necessidade de eliminar links simbólicos etc.), mas se eu tivesse um pouco mais de dados para copiar, valeria o investimento de tempo para fazer isso.dump(8)
um NAS montado sobre NFS. Na época, eu diagnosticava o problema como maximizar a CPU no NAS, devido ao efeito combinado do servidor NFS e um firewall em execução no NAS (a caixa não estava enraizada e o firewall não podia ser desativado completamente de a interface da web). O problema desapareceu quando substituímos o NAS por um PC antigo. FWIW.