Temos esse sistema em produção pesada com mais de 30.000 arquivos e mais de 20 GB até o momento...
Column | Type | Modifiers
-------------+-----------------------------+----------------------------------------------------------
File_ID | integer | not null default nextval('"ACRM"."File_pseq"'::regclass)
CreateDate | timestamp(6) with time zone | not null default now()
FileName | character varying(255) | not null default NULL::character varying
ContentType | character varying(128) | not null default NULL::character varying
Size | integer | not null
Hash | character varying(40) | not null
Indexes:
"File_pkey" PRIMARY KEY, btree ("File_ID")
Os arquivos são armazenados em um único diretório com o inteiro File_ID como nome do arquivo. Já somos mais de 30.000 sem problemas. Eu testei mais alto sem problemas.
Isso está usando RHEL 5 x86_64 com ext3 como o sistema de arquivos.
Eu faria assim de novo? Não. Deixe-me compartilhar algumas ideias sobre uma reformulação.
-
O banco de dados ainda é a "fonte mestra" de informações sobre os arquivos.
-
Cada arquivo tem hash sha1() e é armazenado em uma hierarquia de sistema de arquivos com base nesse hash:/FileData/ab/cd/abcd4548293827394723984723432987.jpg
-
o banco de dados é um pouco mais inteligente quanto ao armazenamento de meta-informações em cada arquivo. Seria um sistema de três tabelas:
File
:armazena informações como nome, data, ip, proprietário e um ponteiro para um Blob (sha1)File_Meta
:armazena pares de chave/valor no arquivo, dependendo do tipo de arquivo. Isso pode incluir informações como Image_Width, etc...Blob
:armazena uma referência ao sha1 junto com seu tamanho.
Esse sistema desduplicaria o conteúdo do arquivo armazenando os dados referenciados por um hash (vários arquivos poderiam referenciar os mesmos dados de arquivo). Seria muito fácil fazer backup de sincronização do banco de dados de arquivos usando rsync.
Além disso, as limitações de um determinado diretório contendo muitos arquivos seriam eliminadas.
A extensão do arquivo seria armazenada como parte do hash de arquivo exclusivo. Por exemplo, se o hash de um arquivo vazio for
abcd8765
... Um .txt
vazio arquivo e vazio .php
arquivo se referiria ao mesmo hash. Em vez disso, eles devem se referir a abcd8765.php
e abcd8765.txt
. Por quê? Apache, etc. podem ser configurados para escolher automaticamente o tipo de conteúdo e as regras de cache com base na extensão do arquivo. É importante armazenar os arquivos com um nome válido e a extensão que reflita o conteúdo do arquivo.
Veja bem, esse sistema pode realmente aumentar o desempenho delegando a entrega de arquivos por meio do nginx. Consulte http://wiki.nginx.org/XSendfile .
Espero que isso ajude de algum jeito. Cuidar.