Seletor de arquivos aleatórios no sistema de arquivos

1

Contexto: Para testar algum processo de backup que deve funcionar todas as noites, eu quero selecionar um arquivo aleatório em uma grande quantidade de dados. (Cerca de 7 milhões de arquivos. Este é um servidor NFS com ~ 8To de dados usados, principalmente aplicativos da Web.

A parte de seleção aleatória precisa ser chamada 2 vezes, primeiro com seleção aleatória pura, e então eu quero pegar alguns arquivos novos (algo como: find / data / -mtime 1 | shuf -n 1) Eu escrevi um script que fez uma análise dos arquivos de configuração de backup, tente restaurar através da ferramenta, compare a soma de verificação original com a antiga e relate todos os testes em um email. Tudo funciona, exceto a "parte de seleção aleatória", na verdade eu tenho alguns problemas de desempenho.

Eu testei muitas maneiras de selecionar arquivos aleatórios em um FS grande. aqui estão algumas das minhas idéias:

  • Selecione inodes usados aleatoriamente e obtendo o nome de arquivo do inode associado (problema de desempenho, para lote de ram necessário, o processo é muito longo).
  • find /data/ -type f -mtime 1 |shuf -n 1 → (Arquivos demais canalizados para o shuf (tempo $ comando ~ 46 segundos))
  • RANDOM=$(shuf -i 1-7000000 -n 1) && find /data/ -type f -mtime 1 |head -n ${RANDOM} → O mesmo problema de desempenho quando aleatório > 1000000 (tempo $ comando ~ 49segundos))
  • Script de descoberta do Python com (os.listdir) → Bom desempenho, mas usei com o ctime, problemas de desempenho horríveis

Estou muito surpreso por não encontrar algumas bibliotecas / ferramentas / scripts (em Python, Bash, C ou qualquer outra coisa) para fazer coisas como explicadas anteriormente. Não parece ser um problema específico, acho que alguns administradores do mundo e testar aleatoriamente se o backup está funcionando corretamente.

Então eu estou interrested de algumas maneiras para fazer isso, com ferramentas específicas do GNU / Linux / BSD / * nix, script / biblioteca Python. Espero que você considere que eu estou procurando por coisas de "alto desempenho". Meu script irá chamar a solução para cada arquivo de configuração de backup de caminho.

Obrigado antecipadamente

    
por DaapTik 24.11.2015 / 11:30

2 respostas

1

A razão pela qual não existe uma 'ferramenta padrão' é porque a lógica é - como você encontrou - bastante simples. O fator limitante é que você deve fazer uma travessia profunda de diretórios, e isso é sempre um processo dispendioso.

Não importa qual abordagem você adota em termos de ferramentas de script - o 'custo' é o IO do disco.

Assim, as otimizações que eu sugeriria seriam:

  • Não ande todo o FS. Bail fora de sua travessia quando você encontrou o suficiente. ( find | shuf e find | head não fazem isso).
  • Você provavelmente pode aproximar o tamanho do diretório referindo-se aos últimos percursos e "avançar" por alguma margem.
  • Os arquivos de estatísticas
  • são processados e a gravação de mtime ajudará você a criar as duas listas. Se você gerar um número aleatório, selecione o último arquivo e o último arquivo recente antes desse número.

Algo parecido com isto (em perl , mas tenho certeza que você poderia fazer isso em Python)

#!/usr/bin/env perl
use strict;
use warnings;

use File::Find;

my $random_file;
my $recent_random_file;

my $limit = rand ( 7_000_000 ); #ideally set to file count on fs. 

sub search {
    if ( $count++ > $limit ) { 
        $File::Find::prune = 1; #stop traversing
        return; 
    }
    return unless -f; 
    if ( -M $File::Find::name < 1 ) { $recent_random_file = $File::Find::name }; 
    $random_file = $File::Find::name; 
}

find ( \&search, "/path/to/search");
print "$recent_random_file $random_file\n";
    
por 24.11.2015 / 12:07
1

Não vejo nenhuma maneira fácil de fazer o que você está tentando realizar. Obter um "arquivo" aleatório do sistema de arquivos grande significa que você deve ter uma lista de todos os arquivos nesse sistema primeiro. O que leva muito tempo ou recursos. Ainda assim, se você quiser seguir esse tipo de solução, aqui está o que posso recomendar:

  • Execute vários processos. Exemplo: Se você tiver sua pasta / data / com 10 subpastas, em vez de find /data/ ..... , poderá fazer algo como:

    for i in "ls data";do find $i ....;done

    Você obterá 10 resultados 10 vezes mais rápido (ou algo parecido). No entanto, consumirá muita CPU.

  • Você não precisa procurar em todo o sistema de arquivos onde milhares de arquivos permanecem os mesmos por anos, mas apenas partes da árvore do sistema de arquivos onde você espera alterações, e excluir partes dos três onde os caches são armazenados , como normalmente eles não se destinam a ser copiados. Dessa forma, você reduzirá o tempo de criação da lista.

  • Defina maxdepth e mindepth (eles podem ser um arquivo aleatório ..) - você ainda obterá um arquivo aleatório, mas limitará os subdiretórios a serem lidos e economizará tempo e recursos.

Tais coisas poderiam ser feitas para ajustar a coisa um pouco, mas quanto maior o sistema de arquivos se tornasse, mais difícil seria conseguir o que você precisa. Talvez seja melhor pensar em solução de backup baseada em snapshot ou em uma maneira melhor de verificar se o backup está correto.

    
por 24.11.2015 / 12:21