Qual é a melhor maneira de projetar um site para ser altamente escalável?

35

Para sites que precisam ser altamente escaláveis, como redes sociais como o facebook, qual é a melhor maneira de criar o site?

  1. Devo ter um serviço da web que o site consulta para obter os dados necessários?

    ou

  2. O site deve consultar os bancos de dados diretamente? (pode ser feito usando construções de linguagem incorporadas para preencher tabelas automaticamente etc).

Eu acho que o serviço da Web é o melhor design, pois fornece acesso centralizado aos dados e coisas como cache e coisas semelhantes se tornam muito mais fáceis de controlar, mas o que os outros pensam?

Daniel
fonte
Há também a questão de qual arquitetura usar (como MVC ou similar).
Ivan
Sem saber mais sobre o que exatamente você vai lançar, é muito difícil dar a resposta, mas lembre-se de "Serviços em nuvem", provavelmente seu aplicativo se encaixa em um tipo de aplicativo SaaS. (É centralizado).
deepcell
de um modo geral eu diria, nada específico em mente ..
Daniel
1
Construa-o na 'nuvem' e gaste muito tempo lendo HighScalability.com.
Evan Solha

Respostas:

37

Uau, esta é uma pergunta simples, com uma enorme variedade de respostas possíveis. A parte mais explícita da sua pergunta pergunta se é mais escalável interagir com seu banco de dados diretamente ou através de um serviço da web. Essa resposta é simples: consulte o banco de dados diretamente. Passar pelo serviço da Web adiciona um monte de latência que é completamente desnecessária para o código que opera atrás de um firewall (em geral). Um serviço da web, por exemplo, exige que algum componente receba uma solicitação, desserialize-a, consulte o banco de dados, serialize uma resposta e a retorne. Portanto, se todo o seu código estiver operando atrás de um firewall, salve-se do problema e consulte o banco de dados diretamente.

Tornar um site escalável, no entanto, vai muito além da pergunta que você fez inicialmente. Então, perdoe-me se eu sair pela tangente aqui, mas achei que seria útil, considerando que você mencionou o Facebook em particular.

Eu recomendaria que você lesse o trabalho e as ferramentas criadas por Brad Fitzpatrick (fundador do LiveJournal e agora no Google). Quando trabalhei com ele no Six Apart, aqui estão algumas das coisas que aprendi com ele e sobre a arquitetura do LiveJournal que a tornou tão escalável.

  1. Use tabelas de banco de dados estreitas em oposição a tabelas amplas . O que foi fascinante foi aprender o que motivou essa arquitetura, que estava criando um sistema que era fácil e rápidoatualizado. Se você usar tabelas amplas, ou tabelas para as quais cada campo ou propriedade é uma coluna da tabela, quando chegar a hora de atualizar o esquema do banco de dados, por exemplo, adicionar uma nova coluna, o sistema precisará bloquear a tabela enquanto o esquema mudança é implementada. Ao operar em escala, isso significaria que uma simples alteração no esquema do banco de dados poderia resultar em uma grande interrupção do banco de dados. O que é péssimo, obviamente. Uma tabela estreita, por outro lado, simplesmente armazena cada propriedade individual associada a um objeto como uma única linha no banco de dados. Portanto, quando você deseja adicionar uma nova coluna ao banco de dados, tudo o que você precisa fazer é INSERIR registros em uma tabela, que é uma operação sem bloqueio. Ok, isso é um pouco de fundo, vamos ver como esse modelo realmente se traduz em sistemas de trabalho como o LiveJournal.

    Digamos que você queira carregar as últimas 10 entradas do diário no blog de uma pessoa e digamos que cada entrada do diário tenha dez propriedades. Em um layout clássico de tabela ampla, cada propriedade se correlacionaria com uma coluna em uma tabela. Um usuário consultaria a tabela uma vez para buscar todos os dados necessários. A consulta retornaria 10 linhas e cada linha teria todos os dados necessários (por exemplo, entradas SELECT * FROM ORDER BY date LIMIT 10). Em um layout de tabela estreito, porém, as coisas são um pouco diferentes. Neste exemplo, existem duas tabelas: a primeira tabela (tabela A) armazena critérios simples pelos quais você deseja pesquisar, por exemplo, o ID da entrada, o ID do autor, a data da entrada etc. Uma segunda tabela (tabela B), em seguida, armazena todas as propriedades associadas a uma entrada. Esta segunda tabela possui três colunas: entry_id, chave e valor. Para cada linha na tabela A, haveria 10 linhas na tabela B (uma linha para cada propriedade). Portanto, para buscar e exibir as últimas dez entradas, você precisaria de 11 consultas. A primeira consulta fornece a lista de IDs de entrada e as próximas dez buscam as propriedades associadas a cada uma das entradas retornadas na primeira consulta.

    "Santo Moly!" você diz: "como na Terra isso pode ser mais escalável ?!" É totalmente contra-intuitivo, certo? No primeiro cenário, tivemos apenas uma consulta ao banco de dados, mas na segunda solução "mais escalável", temos 11 consultas ao banco de dados. Isso não faz sentido. A resposta para essa pergunta depende inteiramente da próxima bala.

  2. Use o memcache liberalmente. Caso você não saiba, o memcache é um sistema de armazenamento em cache distribuído, sem estado e de baixa latência, baseado em rede. É usado pelo Facebook, Google, Yahoo e praticamente todos os sites populares e escaláveis ​​do planeta. Foi inventado por Brad Fitzpatrick parcialmente para ajudar a compensar a sobrecarga do banco de dados inerente a um design de banco de dados de tabela estreita. Vamos dar uma olhada no mesmo exemplo, como discutido no item 1 acima, mas desta vez, vamos apresentar o memcache.

    Vamos começar quando um usuário visita uma página pela primeira vez e nada está no cache. Você começa consultando a tabela A, que retorna os IDs das 10 entradas que você deseja exibir na página. Para cada uma dessas entradas, você consulta o banco de dados para recuperar as propriedades associadas a essa entrada e, em seguida, usá-las constitui um objeto com o qual seu código pode interagir (por exemplo, um objeto). Em seguida, você esconde esse objeto (ou uma forma serializada desse objeto) no memcache.

    Na segunda vez que alguém carrega a mesma página, você começa da mesma maneira: consultando a tabela A para obter a lista de IDs de entrada que você exibirá. Para cada entrada, você primeiro acessa o memcache e diz: "você tem a entrada #X no cache?" Se sim, o memcache retornará o objeto de entrada para você. Caso contrário, será necessário consultar o banco de dados novamente para buscar suas propriedades, constituir o objeto e armazená-lo no memcache. Na maioria das vezes, na segunda vez que alguém visita a mesma página, há apenas uma consulta ao banco de dados, todos os outros dados são extraídos diretamente do memcache.

    Na prática, o que acabou acontecendo na maior parte do LiveJournal é que a maioria dos dados do sistema, especialmente os menos voláteis, foi armazenada em cache no memcache e as consultas extras ao banco de dados necessárias para suportar o esquema de tabela restrita foram quase completamente compensadas.

    Esse design tornou mais fácil a solução do problema associado à montagem de uma lista de postagens associadas a todos os seus amigos em um fluxo ou "mural" .

  3. Em seguida, considere particionar seu banco de dados. O modelo discutido acima apresenta outro problema, e suas tabelas estreitas tendem a ser muito grandes / longas. E quanto mais linhas essas tabelas apresentarem, mais difíceis serão as tarefas administrativas. Para compensar isso, pode fazer sentido gerenciar o tamanho de suas tabelas particionando-as de alguma maneira, para que grupos de usuários sejam atendidos por um banco de dados e outro grupo de usuários seja atendido por um banco de dados separado. Isso distribui a carga no banco de dados e mantém as consultas eficientes.

  4. Finalmente, você precisa de índices impressionantes. A velocidade das suas consultas dependerá em grande parte de quão bem as tabelas do seu banco de dados estão indexadas. Não vou gastar muito tempo discutindo o que é um índice, exceto para dizer que é muito parecido com um sistema gigante de catálogo de cartões para tornar mais eficiente a localização de agulhas no palheiro. Se você usa o mysql, recomendo ativar o log de consultas lentas para monitorar as consultas que demoram muito tempo para serem atendidas. Quando uma consulta aparecer no seu radar (por exemplo, porque é lenta), descubra qual índice você precisa adicionar à tabela para acelerar.

"Obrigado por todo esse excelente histórico, mas, caramba, isso é muito código que terei que escrever."

Não necessariamente. Muitas bibliotecas foram escritas para facilitar a interface com o memcache. Outras bibliotecas ainda codificaram todo o processo descrito acima; Data :: ObjectDriver no Perl é apenas uma biblioteca. Quanto a outros idiomas, você precisará fazer sua própria pesquisa.

Espero que você tenha achado esta resposta útil. O que eu descobri com mais frequência é que a escalabilidade de um sistema se reduz cada vez menos ao código, e cada vez mais a uma boa estratégia de armazenamento e gerenciamento de dados / design técnico.

Byrne Reese
fonte
3
+1 Eu realmente amo esse Wow, essa é uma pergunta simples, com uma enorme variedade de respostas possíveis.
Pankaj Upadhyay
1
Eu discordo completamente de 'consultar o banco de dados diretamente'. Você mencionou o particionamento do banco de dados para desempenho, quando seria mais fácil implementar uma arquitetura de múltiplos escravos de mestre único com uma interface de API. O benefício de dissociar o banco de dados do aplicativo é que a camada da API pode distribuir solicitações da maneira que desejar. A API é uma abstração que permite alterar a implementação subjacente e / ou reutilizar os dados sem interromper o aplicativo.
Evan Solha
1
(cont) A serialização sempre adiciona sobrecarga, mas apenas na camada da API, que provavelmente consistirá em várias instâncias sendo executadas simultaneamente. Se você estiver preocupado com a velocidade de transferência, converta para JSON e provavelmente será compactado com o gzip. Os ganhos de desempenho mais fáceis podem ser encontrados quando o trabalho é enviado do servidor para o cliente. A pergunta importante a fazer é: você prefere distribuir solicitações no aplicativo ou no nível do servidor? Qual é mais fácil de duplicar?
Evan Solha
1
@EvanPlaice - Grandes pontos sobre reutilização e alteração da implementação da lógica de serviço ao usar serviços. Além disso, a infraestrutura de cache também pode ser usada pelos serviços, em vez de chamadas diretas ao banco de dados.
Ashish Gupta
1
@AshishGupta Exatamente, a única diferença no particionamento dos dados em um serviço separado é o que o usuário recebe. Em vez disso, monte o conteúdo html + no servidor. O usuário recebe dados e html separados e o navegador do cliente lida com a remontagem. Com os dados como um serviço separado, também é possível disponibilizá-los para aplicativos móveis ou outros clientes não baseados na Web (por exemplo, aplicativos de TV inteligente).
Evan Plaice
13

Para sites que precisam ser altamente escaláveis, como redes sociais como o facebook, qual é a melhor maneira de criar o site?

A medida.

Eu acho que o ...

Política ruim.

A medição real é necessária.

S.Lott
fonte
Métricas quantitativas FTW.
bhagyas
1
Ok ... então o que é depois da medição?
Pacerier
9

A escalabilidade não é uma função de estratégias de implementação específicas, mas de projetar a arquitetura do aplicativo para que a camada de acesso a dados possa evoluir sem refatoração e reescrita maciça.

Uma técnica importante na construção de um sistema escalável é entender seus requisitos de acesso a dados de alto nível e criar um contrato de interface em torno deles. Por exemplo, você pode ter o requisito de obter um usuário ou listar as 50 fotos postadas mais recentemente por qualquer usuário .

Você não precisa necessariamente de um canal de rede entre a lógica de negócios do aplicativo e a lógica de acesso a dados; um método de chamada indireta com um método por operação lógica seria bom para iniciar.

Faça com que esses métodos de acesso a dados sejam o mais simples possível. É muito difícil prever onde estão os problemas de desempenho até que seu aplicativo atenda a padrões de uso reais e você esteja coletando dados sobre onde há gargalos.

Por ter uma interface de acesso a dados bem definida, você pode evoluir sua implementação de acesso a dados sem fazer grandes alterações em todo o aplicativo. Você também pode optar por mudar para uma arquitetura de serviço da web de forma transparente para sua lógica de negócios.

Muitas das respostas acima fornecem ótimos conselhos sobre como proceder depois que você descobre os gargalos de desempenho, mas se você aplicá-los muito cedo, poderá ficar prejudicado pela complexidade do seu código antes de saber se essa complexidade é necessária.

Martin Atkins
fonte
4

Desenvolva um site simples e permita que ele atinja algum nível de tráfego. Nessa linha, você aprenderá como criar sites escaláveis.

Até enfrentar o problema, você não consegue pensar em solução .

Confie em mim quando tiver o site rodando e enfrentando os requisitos de dimensionamento, você definitivamente saberá como fazer isso. :-)

Pankaj Upadhyay
fonte
Good Quote !!!!!!!!!!
AmirHossein 13/08/19
2

É aceito que aplicativos da Web sejam projetados com três camadas por padrão - camadas Web (apresentação), aplicativo e banco de dados. Essa divisão se deve a requisitos diferentes em cada uma das camadas - normalmente acesso / armazenamento em disco de qualidade para o banco de dados, alta CPU / Memória na camada de aplicativo e alta largura de banda externa / memória / dispersão geográfica na camada da web. A camada de aplicativo / banco de dados geralmente é mesclada em uma até muito mais tarde no ciclo de vida do aplicativo, pois as máquinas de banco de dados tendem a ser servidores massivos que podem ser criados para lidar também com o carregamento inicial do aplicativo.

O número específico de camadas e a arquitetura apropriada para seu aplicativo, no entanto, não precisam corresponder a este ou qualquer outro modelo.

Planeje a necessidade de medir e monitorar toda a atividade em seu sistema. Comece com um design de duas ou três camadas e concentre-se nas partes que, ao serem construídas, parecerão exigir a maior quantidade de recursos. Deixe o aplicativo em execução guiar seu design, neste nível. Quanto mais informações você coletar, e quanto mais precisas e detalhadas forem, melhores decisões você poderá tomar sobre o design do aplicativo à medida que ele cresce.

Escolha uma estrutura e uma arquitetura que, posteriormente, permitirão que você gire / faça as alterações necessárias da maneira mais rápida e fácil possível. Mesmo que seu acesso a dados / armazenamento / processamento e processamento de aplicativos estejam sendo executados no mesmo executável, se eles forem devidamente fatorados, não será tão difícil dividi-los em duas camadas mais tarde, por exemplo.

blueberryfields
fonte
2

Qualquer etapa adicional na conexão com o banco de dados é apenas uma sobrecarga. Por exemplo, entre UI -> Business Facade -> Business -> Data Access -> Databasee UI -> Database, a segunda abordagem é mais rápida. No entanto, quanto mais etapas você remover, menor será a manutenção do seu sistema e mais duplicação será exibida. Imagine escrever o código necessário para recuperar a lista de amigos no perfil, na página inicial, na página de gerenciamento de demônios, etc.

Portanto, você deve fazer um equilíbrio aqui entre maior desempenho (o que naturalmente afeta diretamente maior escalabilidade) e melhor manutenção .

Mas não se limite ao tópico de conexão com o banco de dados ao pensar em criar sites altamente escaláveis. Considere estes itens também:

  1. Escolhendo a plataforma certa (PHP é mais rápido devido à sua natureza de script, mas ASP.NET precisa compilar o arquivo solicitado em tempo real para processá-lo e servir algo. Também node.js é reivindicada a ser mais escalável, devido à sua callback- arquitetura baseada em )
  2. Usando a arquitetura RESTful em vez do modelo de serviço da web (SOA)
  3. Usando JSON para transferência de dados em vez de XML (o que resulta em menos bytes a serem transferidos)
  4. Seguindo as diretrizes de desempenho do Yahoo
  5. Tópicos de rede e hardware, como balanceamento de carga ou arquitetura de camadas
Saeed Neamati
fonte
2
Você não pode dizer que o PHP é mais rápido. Aplicativos ASP.NET escritos corretamente podem superar o PHP em muitos casos. Naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
Andrew Lewis
+1 Na verdade, sua solução 'simples' será: UI -> Acesso a Dados -> Banco de Dados. 2 O REST é 'fácil' porque já está incorporado na maioria dos navegadores. Não há necessidade de recriar a roda da API de resposta ao comando. 3 O JSON não é apenas menor, mas requer menos etapas para serializar-desserializar, porque você não precisa procurar entidades HTML. Coisa boa.
Evan Solha
1

Existem duas maneiras principais de expandir, aumentar e diminuir.

Aumentar a escala está substituindo uma máquina por uma mais poderosa. Escalar significa adicionar outra máquina para fazer o trabalho que as máquinas existentes estão fazendo.

Qualquer site de alto tráfego precisa da capacidade de expansão. A arquitetura do software precisa ser feita de maneira a permitir que mais máquinas possam ser adicionadas facilmente quanto mais ocupado o site ficar.

Geralmente, isso significa dividir o aplicativo em camadas, para que você possa conectar e reproduzir mais servidores em cada camada.

Eu faria a opção 1, teria um serviço em vez de fazê-lo diretamente. Você só pode dimensionar um aplicativo monolítico até o momento.

Jon Raynor
fonte
0

Desenvolva seu site usando uma plataforma de tecnologia que tenha suporte completamente integrado para a nuvem.

bhagyas
fonte