Digamos que estamos usando o ext4 (com o dir_index ativado) para hospedar cerca de 3 milhões de arquivos (com uma média de tamanho de 750 KB) e precisamos decidir qual esquema de pastas usaremos.
Na primeira solução , aplicamos uma função de hash ao arquivo e usamos a pasta de dois níveis (sendo 1 caractere para o primeiro nível e 2 caracteres para o segundo nível): portanto, sendo o filex.for
hash igual a abcde1234 , vamos armazená-la no / path / a / bc /abcde1234-filex.for.
Na segunda solução , aplicamos uma função de hash ao arquivo e usamos a pasta de dois níveis (sendo 2 caracteres para o primeiro nível e 2 caracteres para o segundo nível): portanto, sendo o filex.for
hash igual a abcde1234 , vamos armazená-la no / path / ab / de /abcde1234-filex.for.
Para a primeira solução, teremos o seguinte esquema /path/[16 folders]/[256 folders]
com uma média de 732 arquivos por pasta (a última pasta, onde o arquivo residirá).
Enquanto na segunda solução, teremos /path/[256 folders]/[256 folders]
uma média de 45 arquivos por pasta .
Considerando que vamos escrever / desvincular / ler arquivos ( mas principalmente ler ) desse esquema (basicamente o sistema de cache nginx), isso agrega, no sentido do desempenho, se escolhermos uma ou outra solução?
Além disso, quais são as ferramentas que poderíamos usar para verificar / testar essa configuração?
fonte
hdparm -Tt /dev/hdX
mas pode não ser a ferramenta mais apropriada.hdparm
não é a ferramenta certa, é uma verificação do desempenho bruto do dispositivo de bloco e não um teste do sistema de arquivos.Respostas:
A razão pela qual você criaria esse tipo de estrutura de diretório é que os sistemas de arquivos devem localizar um arquivo em um diretório e, quanto maior o diretório, mais lenta será a operação.
Quanto mais lento depende do design do sistema de arquivos.
O sistema de arquivos ext4 usa uma árvore B para armazenar entradas de diretório. Espera-se que uma pesquisa nesta tabela demore O (log n) , que na maioria das vezes é menor que a tabela linear ingênua usada pelos sistemas de arquivos ext3 e anteriores (e quando não é, o diretório é muito pequeno para ser usado). realmente importa).
O sistema de arquivos XFS usa uma árvore B + . A vantagem disso sobre uma tabela de hash ou uma árvore B é que qualquer nó pode ter vários filhos b , onde no XFS b varia e pode chegar a 254 (ou 19 no nó raiz; e esses números podem estar desatualizados ) Isso fornece uma complexidade de tempo de O (log b n) , uma grande melhoria.
Qualquer um desses sistemas de arquivos pode lidar com dezenas de milhares de arquivos em um único diretório, com o XFS sendo significativamente mais rápido que o ext4 em um diretório com o mesmo número de inodes. Mas você provavelmente não deseja um único diretório com inodes da 3M, pois mesmo com uma árvore B +, a pesquisa pode levar algum tempo. Isso foi o que levou à criação de diretórios dessa maneira em primeiro lugar.
Quanto às estruturas propostas, a primeira opção que você deu é exatamente o que é mostrado nos exemplos do nginx. Ele terá um bom desempenho em qualquer sistema de arquivos, embora o XFS ainda tenha um pouco de vantagem. A segunda opção pode ter um desempenho um pouco melhor ou um pouco pior, mas provavelmente será bem próxima, mesmo em benchmarks.
fonte
ls -l
leva um minuto inteiro se o diretório caiu do cache do inode. E quando é armazenado em cache, ainda leva mais de um segundo. Isso ocorre com um SSD e um Xeon com toneladas de RAM em um servidor Web de tráfego bastante baixo.Na minha experiência, um dos fatores de escala é o tamanho dos inodes, dada uma estratégia de particionamento de nome de hash.
As duas opções propostas criam até três entradas de inode para cada arquivo criado. Além disso, 732 arquivos criarão um inode ainda menor que o normal de 16 KB. Para mim, isso significa que qualquer uma das opções executará o mesmo.
Aplaudo por seu curto hash; sistemas anteriores em que trabalhei pegaram o sha1sum do arquivo fornecido e os diretórios emendados com base nessa string, um problema muito mais difícil.
fonte
Certamente qualquer uma das opções ajudará a reduzir o número de arquivos em um diretório para algo que pareça razoável, para xfs ou ext4 ou qualquer outro sistema de arquivos. Não é óbvio o que é melhor, teria que testar para contar.
O benchmark com seu aplicativo simulando algo como a carga de trabalho real é ideal. Caso contrário, crie algo que simule especificamente muitos arquivos pequenos. Falando nisso, aqui está um código aberto chamado smallfile . Sua documentação faz referência a outras ferramentas.
hdparm
fazer E / S sustentada não é tão útil. Não mostrará muitas entradas / entradas pequenas de diretório ou gigantes associadas a muitos arquivos.fonte
Um dos problemas é a maneira de verificar a pasta.
Imagine o método Java que executa a verificação na pasta.
Ele precisará alocar grande quantidade de memória e desalocá-la em um curto período de tempo, o que é muito pesado para a JVM.
A melhor maneira é organizar a estrutura de pastas da maneira que cada arquivo está na pasta dedicada, por exemplo, ano / mês / dia.
A maneira como a verificação completa é feita é que, para cada pasta, há uma execução da função, portanto a JVM sai da função, desaloca a RAM e a executa novamente em outra pasta.
Este é apenas um exemplo, mas de qualquer maneira ter uma pasta tão grande não faz sentido.
fonte
Eu estou tendo o mesmo problema. Tentando armazenar milhões de arquivos em um servidor Ubuntu no ext4. Acabei de executar meus próprios benchmarks. Descobriu que o diretório simples tem um desempenho muito melhor e é muito mais simples de usar:
Escreveu um artigo .
fonte