Sincronizando estruturas de pastas muito grandes

14

Temos uma estrutura de pastas em nossa intranet que contém cerca de 800.000 arquivos divididos em cerca de 4.000 pastas. Precisamos sincronizar isso com um pequeno cluster de máquinas em nossas DMZs. A profundidade da estrutura é muito rasa (nunca excede dois níveis).

A maioria dos arquivos nunca muda, todos os dias existem alguns milhares de arquivos atualizados e 1-2 mil novos arquivos. Os dados são dados históricos de relatórios sendo mantidos onde os dados de origem foram limpos (ou seja, são relatórios finalizados para os quais os dados de origem são suficientemente antigos para arquivá-los e excluí-los). A sincronização uma vez por dia é suficiente, pois isso pode ocorrer em um período de tempo razoável. Os relatórios são gerados da noite para o dia e sincronizamos a primeira coisa da manhã como uma tarefa agendada.

Obviamente, como poucos arquivos são alterados regularmente, podemos nos beneficiar muito com a cópia incremental. Tentamos o Rsync, mas isso pode levar de oito a doze horas apenas para concluir a operação "lista de arquivos de construção". É claro que estamos superando rapidamente o que o rsync é capaz (o período de 12 horas é muito longo).

Estávamos usando outra ferramenta chamada RepliWeb para sincronizar as estruturas e ela pode fazer uma transferência incremental em cerca de 45 minutos. No entanto, parece que excedeu seu limite, ele começou a ver os arquivos sendo exibidos como exclusões quando não estão (talvez alguma estrutura de memória interna tenha sido esgotada, não temos certeza).

Alguém mais se deparou com um projeto de sincronização em larga escala desse tipo? Existe algo projetado para lidar com estruturas de arquivos maciças como esta para sincronização?

MightyE
fonte
Você já tentou dividir o trabalho em várias instâncias do rsync em execução ao mesmo tempo? Não tenho uma imagem muito boa da estrutura de diretórios, mas você pode dividi-la por nome de diretório ou nome de arquivo.
Embraiagem
Nós tínhamos pensado nisso, mas com uma estrutura tão plana, é difícil encontrar boas linhas divisórias para dividir o trabalho. É complicado pelo fato de as pastas terem nomes muito parecidos (existe uma convenção de nomenclatura que faz com que a maioria das pastas comece com o mesmo conjunto inicial de 6 caracteres).
MightyE
Você já encontrou uma boa solução, Dave? Estou pensando lsyncd para um dir com 65535 sub-diretórios, cada um dos quais poderia ter 65 ^ 16 arquivos.
Mike Diehn
1
@ MikeDiehn Eu nunca encontrei uma ferramenta que eu estava totalmente feliz aqui. Conseguimos a ferramenta proprietária RepliWeb para corrigir o erro, onde eles viam arquivos como exclusões que não eram, era uma estrutura interna transbordada. Eu deixei o emprego anos atrás, presumo que eles ainda estejam usando isso. Para seus propósitos, se seus diretórios estiverem razoavelmente distribuídos, você poderá usar algo como a solução de Ryan. Ele não notará exclusões de nível superior, mas 65535 subdiretórios sugerem que você provavelmente não as possui.
MightyE 26/10/14

Respostas:

9

Se você pode confiar nos carimbos de data e hora da última modificação do sistema de arquivos, pode acelerar as coisas combinando o Rsync com o utilitário 'find' do UNIX / Linux. O 'find' pode montar uma lista de todos os arquivos que mostram os horários da última modificação nos últimos dias e depois canalizar APENAS essa lista reduzida de arquivos / diretórios para o Rsync. Isso é muito mais rápido do que o Rsync comparar os metadados de cada arquivo no remetente com o servidor remoto.

Em resumo, o seguinte comando executará o Rsync SOMENTE na lista de arquivos e diretórios que foram alterados nas últimas 24 horas: (o Rsync NÃO se preocupará em verificar outros arquivos / diretórios.)

find /local/data/path/ -mindepth 1 -ctime -0 -print0 | xargs -0 -n 1 -I {} -- rsync -a {} remote.host:/remote/data/path/.

Caso você não esteja familiarizado com o comando 'find', ele se repete através de uma subárvore de diretório específica, procurando arquivos e / ou diretórios que atendam aos critérios especificados. Por exemplo, este comando:

find . -name '\.svn' -type d -ctime -0 -print

será iniciado no diretório atual (".") e será repetido em todos os subdiretórios, procurando:

  • qualquer diretório ("-type d"),
  • chamado ".svn" ("-name '.svn'"),
  • com metadados modificados nas últimas 24 horas ("-ctime -0").

Ele imprime o nome do caminho completo ("-print") de qualquer coisa que corresponda a esses critérios na saída padrão. As opções '-name', '-type' e '-ctime' são chamadas de "testes" e a opção '-print' é chamada de "ação". A página de manual para 'find' possui uma lista completa de testes e ações.

Se você quiser ser realmente inteligente, poderá usar o teste '-newer' do comando 'find', em vez de '-ctime' para tornar esse processo mais tolerante a falhas e flexível. '-cnewer' testa se cada arquivo / diretório na árvore teve seus metadados modificados mais recentemente do que algum arquivo de referência. Use 'touch' para criar o arquivo de referência da próxima execução no início de cada execução, logo antes de 'localizar ... | O comando rsync ... 'é executado. Aqui está a implementação básica:

#!/bin/sh
curr_ref_file=`ls /var/run/last_rsync_run.*`
next_ref_file="/var/run/last_rsync_run.$RANDOM"
touch $next_ref_file
find /local/data/path/ -mindepth 1 -cnewer $curr_ref_file -print0 | xargs -0 -n 1 -I {} -- rsync -a {} remote.host:/remote/data/path/.
rm -f $curr_ref_file

Esse script sabe automaticamente quando foi a última execução e só transfere arquivos modificados desde a última execução. Embora isso seja mais complicado, ele protege você contra situações nas quais você pode ter perdido a execução do trabalho por mais de 24 horas, devido a tempo de inatividade ou algum outro erro.

Ryan B. Lynch
fonte
Esta é uma solução extremamente inteligente! Eu estou pensando que você pretende touch $next_ref_fileno final? Isso nos deixa sem a capacidade de lidar com caminhos excluídos (mesmo esses relatórios estáticos de arquivamento acabam ficando velhos o suficiente para serem arquivados e excluídos). Isso pode não ser um obstáculo para o show.
MightyE
Estou descobrindo, no entanto, que mesmo assim find . -ctime 0é muito lento nessa estrutura de diretórios (ainda estou aguardando a conclusão para relatar seu tempo). Isso realmente me desanima um pouco, porque parece que essa pode ser uma operação de nível bastante baixo, que provavelmente define a fasquia para o mais rápido que poderíamos esperar que esse trabalho fosse concluído. Pode ser que a E / S do disco seja o fator limitante aqui.
MightyE
Quanto ao scriptlet, sim, cometi um erro. Eu quis dizer executar 'touch' no 'next_ref_file' (NÃO 'curr_ref_file') logo antes de executar o 'find ... | comando rsync ... '. (Eu vou corrigir minha resposta.)
Ryan B. Lynch
3
Quanto ao comando lento 'find': Que tipo de sistema de arquivos você está usando? Se você estiver usando o Ext3, considere dois ajustes de FS: 1) Execute 'tune2fs -O dir_index <DEVICE_NODE>' para ativar o recurso 'dir_index' do Ext3, para acelerar o acesso a diretórios com grandes contagens de arquivos. 2) Execute 'mount -o remount, noatime, nodiratime' para desativar as atualizações do tempo de acesso, o que acelera a leitura em geral. 'dumpe2fs -h <DEVICE_NODE> | grep dir_index 'informa se' dir_index 'já está ativado (em algumas distros, é o padrão) e' mount | grep <DEVICE_NODE> 'informa sobre atualizações de tempo de acesso.
Ryan B. Lynch
Infelizmente, é NTFS - Windows 2003 Server usando Cygwin para o comando find. Eu lembrarei das opções de ajuste (excelentes conselhos) para o ext3, caso alguma vez encontremos algo semelhante em um de nossos clusters Debian.
MightyE
7

Experimente o uníssono , ele foi projetado especificamente para resolver esse problema, mantendo as listas de alterações (lista de arquivos de construção), localmente em cada servidor, acelerando o tempo para calcular o delta e a quantidade reduzida que é enviada posteriormente pela conexão.

Dave Cheney
fonte
Estou experimentando Unison. Ele está em execução há cerca de 2 horas no estágio "Procurando por alterações" e, com base nos arquivos em que está trabalhando, parece que está na metade do caminho (portanto, talvez 4 horas no total antes do início da transferência). Parece que será melhor que o rsync, mas ainda fora da nossa janela operacional desejada.
MightyE
2
Na primeira vez em que você cria um índice nos dois lados, os tempos de reconstrução são semelhantes ao rsync, pois precisam fazer o hash de cada arquivo. Uma vez feito isso, o unison usa o horário da última modificação do diretório para identificar quando um arquivo foi alterado e apenas precisa verificar se há alterações.
Dave Cheney
Infelizmente, eu fui vítima de um administrador de operações muito zeloso que encerrou minha sessão antes da criação do catálogo (limitamos o número de logons simultâneos aos servidores de produção). Perdi o progresso que havia feito na criação do catálogo inicial, por isso tenho que começar de novo. Eu vou deixar você saber como vai.
MightyE
Agora leva cerca de 2 horas para que o catálogo inicial seja criado para verificar alterações. Estou bastante surpreso com a quantidade de RAM que a Unison está usando para isso. Para nossa coleção de arquivos, o servidor de origem está usando 635M e o cliente remoto está usando 366M. Sincronizar várias máquinas em um cluster seria uma pegada bastante pesada, principalmente para o servidor de origem!
MightyE
1
Você consegue estruturar seus dados de maneira a facilitar a identificação dos dados que foram alterados recentemente? Ou seja, armazená-lo no formato ano / mês / dia / ...?
Dave Cheney
2

Se você estiver usando a opção -z no rsync, tente executar sem ela. Por alguma razão, eu já vi isso acelerar até a enumeração inicial de arquivos.

Chris Thorpe
fonte
Tentamos com e sem a bandeira -z. Não pareceu afetar a duração da execução da "lista de arquivos de construção".
MightyE
2

Tirar -z do comando rsync, que não é compactação, fez com que a "lista de arquivos de recebimento" fosse muito mais rápida e tivemos que transferir cerca de 500 GB. Antes de levar um dia com a opção -z.

ryand32
fonte