Pergunta

Estou construindo um aplicativo que inclui um recurso para marcar milhões de registros em massa, de forma mais ou menos interativa.A interação do usuário é muito semelhante ao Gmail, onde os usuários podem marcar e-mails individuais ou marcar em massa grandes quantidades de e-mails.Também preciso de acesso de leitura rápida a essas associações de tags e onde o padrão de leitura é mais ou menos aleatório.

No momento estamos usando Mysql e inserindo uma linha para cada par tag-documento.Escrever milhões de linhas no Mysql demora um pouco (alta E/S), mesmo com inserções em massa e otimização pesada.Precisamos que seja um processo interativo, não um processo em lote.

Para os dados que armazenamos e lemos, a consistência e a disponibilidade dos dados não são tão importantes quanto o desempenho e a escalabilidade.Portanto, no caso de falha do sistema durante a ocorrência das gravações, posso lidar com alguma perda de dados.No entanto, os dados definitivamente precisam ser mantidos no armazenamento secundário em algum momento.

Então, para resumir, aqui estão os requisitos:

  • Gravações em massa de baixa latência de potencialmente dezenas de milhões de registros
  • Os dados precisam ser persistidos de alguma forma
  • Leituras aleatórias de baixa latência
  • Gravações duráveis ​​não são necessárias
  • Consistência eventual está bem

Aqui estão algumas soluções que observei:

  • Escreva atrás de caches (Terracotta, Gigaspaces, Coherence) onde os registros são gravados na memória e drenados para o banco de dados de forma assíncrona.Isso me assusta um pouco porque parece adicionar uma certa complexidade ao aplicativo que eu gostaria de evitar.
  • Armazenamentos de valores-chave altamente escaláveis, como MongoDB, HBase, Tokyo Tyrant
Foi útil?

Solução

Se você tiver orçamento para usar o Coherence para isso, recomendo enfaticamente que o faça.Há suporte direto para comportamento de consistência eventual e write-behind no Coherence e é muito resistente a interrupções de banco de dados e interrupções de nós de cluster do Coherence (se você usar >= 3 nós do Coherence em JVMs separadas, de preferência em hosts separados).Eu implementei isso para fazer CRM de alto volume para o site de comércio eletrônico de uma empresa Fortune 100 e funciona de maneira fantástica.

Um dos melhores aspectos dessa arquitetura é que você escreve o código do aplicativo Java como se nenhum comportamento de gravação por trás estivesse ocorrendo e, em seguida, conecta a topologia e a configuração do Coherence que fazem isso acontecer.Se você precisar alterar o comportamento ou a topologia do Coherence posteriormente, nenhuma alteração em seu aplicativo será necessária.Eu sei que provavelmente existem algumas maneiras razoáveis ​​de fazer isso, mas esse comportamento é diretamente apoiado no Coherence, em vez de ter que inventar ou rolar manualmente uma maneira de fazê-lo.

Para deixar claro: sua preocupação em adicionar complexidade ao aplicativo é boa.Com o Coherence, você simplesmente escreve atualizações no cache (ou, se estiver usando o Hibernate, pode ser o provedor de cache L2).Dependendo da configuração e topologia do Coherence, você tem a opção de implantar seu aplicativo para usar caches distribuídos e write-behind.Portanto, sua aplicação não é mais complexa (e, francamente, inconsciente) devido aos recursos do cache.

Por fim, implementei a solução mencionada acima entre 2005-2007, quando o Coherence foi feito pela Tangosol e eles tiveram o melhor suporte possível.Não tenho certeza de como as coisas estão agora no Oracle - espero que ainda estejam boas.

Outras dicas

Eu trabalhei em um grande projeto que usava gravações assíncronas, embora nesse caso fosse apenas escrito à mão usando threads em segundo plano.Você também pode implementar algo assim descarregando o processo de gravação do banco de dados para uma fila JMS.

Uma coisa que certamente irá acelerar as gravações do banco de dados é fazê-las em lotes.As atualizações em lote JDBC podem ser muito mais rápidas do que as gravações individuais e, se você as fizer de forma assíncrona, poderá gravá-las 500 por vez.

Dependendo de como seus dados estão organizados, talvez você possa usar fragmentação, se a latência de leitura não for baixa o suficiente, você também pode tentar adicionar armazenamento em cache.Memcache é uma solução popular.

Berkeley DB possui uma tabela hash baseada em disco de altíssimo desempenho que suporta transações e se integra a um ambiente Java EE, se necessário.Se você conseguir modelar os dados como pares chave/valor, esta pode ser uma solução muito escalonável.

http://www.oracle.com/technology/products/berkeley-db/je/index.html

(Observação:a Oracle comprou o Berkeley DB há cerca de 5 a 10 anos;o produto original existe há 15-20 anos).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top