Gostaríamos de armazenar milhões de arquivos de texto em um sistema de arquivos Linux, com o objetivo de compactar e servir uma coleção arbitrária como um serviço. Tentamos outras soluções, como um banco de dados de chave/valor, mas nossos requisitos de simultaneidade e paralelismo tornam o uso do sistema de arquivos nativo a melhor escolha.
A maneira mais direta é armazenar todos os arquivos em uma pasta:
$ ls text_files/
1.txt
2.txt
3.txt
o que deve ser possível em um sistema de arquivos EXT4 , que não tem limite para o número de arquivos em uma pasta.
Os dois processos FS serão:
- Escreva o arquivo de texto do web scrape (não deve ser afetado pelo número de arquivos na pasta).
- Compacte os arquivos selecionados, fornecidos pela lista de nomes de arquivos.
Minha pergunta é: o armazenamento de até dez milhões de arquivos em uma pasta afetará o desempenho das operações acima ou o desempenho geral do sistema, de maneira diferente de criar uma árvore de subpastas para os arquivos residirem?
Isso é perigosamente próximo a uma pergunta/resposta baseada em opinião, mas tentarei fornecer alguns fatos com minhas opiniões.
mv * /somewhere/else
, ) pode não conseguir expandir o curinga com êxito ou o resultado pode ser muito grande para ser usado.ls
levará mais tempo para enumerar um número muito grande de arquivos do que um pequeno número de arquivos.Uma recomendação é dividir o nome do arquivo em dois, três ou quatro blocos de caracteres e usá-los como subdiretórios. Por exemplo,
somefilename.txt
pode ser armazenado comosom/efi/somefilename.txt
. Se você estiver usando nomes numéricos, divida da direita para a esquerda em vez da esquerda para a direita para que haja uma distribuição mais uniforme. Por exemplo12345.txt
, pode ser armazenado como345/12/12345.txt
.Você pode usar o equivalente
zip -j zipfile.zip path1/file1 path2/file2 ...
a para evitar a inclusão de caminhos de subdiretórios intermediários no arquivo ZIP.Se você estiver servindo esses arquivos de um servidor da Web (não tenho certeza se isso é relevante), é trivial ocultar essa estrutura em favor de um diretório virtual com regras de reescrita no Apache2. Eu diria que o mesmo é verdade para o Nginx.
O
ls
comando, ou mesmo TAB-completion ou expansão curinga pelo shell, normalmente apresentará seus resultados em ordem alfanumérica. Isso requer a leitura de toda a lista de diretórios e sua classificação. Com dez milhões de arquivos em um único diretório, essa operação de classificação levará um tempo não desprezível.Se você puder resistir ao desejo de completar TAB e, por exemplo, escrever os nomes dos arquivos a serem compactados por completo, não haverá problemas.
Outro problema com curingas pode ser a expansão do curinga, possivelmente produzindo mais nomes de arquivos do que cabem em uma linha de comando de comprimento máximo. O comprimento máximo típico da linha de comando será mais do que adequado para a maioria das situações, mas quando estamos falando de milhões de arquivos em um único diretório, isso não é mais uma suposição segura. Quando um comprimento máximo da linha de comando é excedido na expansão curinga, a maioria dos shells simplesmente falhará em toda a linha de comando sem executá-la.
Isso pode ser resolvido fazendo suas operações curinga usando o
find
comando:ou uma sintaxe semelhante sempre que possível. O
find ... -exec ... \+
levará automaticamente em consideração o comprimento máximo da linha de comando e executará o comando quantas vezes for necessário, ajustando a quantidade máxima de nomes de arquivo a cada linha de comando.Eu administro um site que lida com um banco de dados para filmes, TV e videogames. Para cada um deles, existem várias imagens com TV contendo dezenas de imagens por programa (ou seja, instantâneos de episódios, etc.).
Acaba havendo muitos arquivos de imagem. Em algum lugar na faixa de mais de 250.000. Todos eles são armazenados em um dispositivo de armazenamento de bloco montado, onde o tempo de acesso é razoável.
Minha primeira tentativa de armazenar as imagens foi em uma única pasta como
/mnt/images/UUID.jpg
Encontrei os seguintes desafios.
ls
através de um terminal remoto iria simplesmente travar. O processo iria zumbi eCTRL+C
não iria quebrá-lo.ls
comando preencheria rapidamente o buffer de saída eCTRL+C
não interromperia a rolagem sem fim.Acabei tendo que armazenar os arquivos em subpastas usando o tempo de criação para criar o caminho. Tal como
/mnt/images/YYYY/MM/DD/UUID.jpg
. Isso resolveu todos os problemas acima e me permitiu criar arquivos zip direcionados a uma data.Se o único identificador de um arquivo que você possui for um número numérico, esses números tendem a ser executados em sequência. Por que não agrupá-los por
100000
e .10000
1000
Por exemplo, se você tiver um arquivo chamado
384295.txt
, o caminho seria:Se você souber, chegará a alguns milhões. Use
0
prefixos para 1.000.000Em primeiro lugar: evite que 'ls' seja classificado com 'ls -U', talvez atualize seu ~/bashrc para ter 'alias ls="ls -U"' ou similar.
Para o seu grande conjunto de arquivos, você pode tentar desta forma:
criar um conjunto de arquivos de teste
veja se muitos nomes de arquivos causam problemas
use xargs parmeter-batching e o comportamento do zip (padrão) de adicionar arquivos a um zip para evitar problemas.
Isso funcionou bem:
Para criar um novo arquivo, é necessário verificar o arquivo do diretório procurando por espaço vazio suficiente para a nova entrada do diretório. Se nenhum espaço localizado for grande o suficiente para armazenar a nova entrada de diretório, ele será colocado no final do arquivo de diretório. À medida que o número de arquivos em um diretório aumenta, o tempo para varrer o diretório também aumenta.
Contanto que os arquivos do diretório permaneçam no cache do sistema, o impacto no desempenho não será ruim, mas se os dados forem liberados, a leitura do arquivo do diretório (geralmente altamente fragmentado) do disco pode consumir um pouco de tempo. Um SSD melhora isso, mas para um diretório com milhões de arquivos, ainda pode haver um impacto perceptível no desempenho.
Isso provavelmente também exigirá tempo adicional em um diretório com milhões de arquivos. Em um sistema de arquivos com entradas de diretório com hash (como EXT4), essa diferença é mínima.
Uma árvore de subpastas não tem nenhuma das desvantagens de desempenho acima. Além disso, se o sistema de arquivos subjacente for alterado para não ter nomes de arquivos com hash, a metodologia da árvore ainda funcionará bem.