Um ano e meio atrás embarquei em um projeto que antes da minha entrada já havia adotado o MongoDB. Meu objetivo neste post é relatar alguns dos nossos erros e acertos.
O que deu certo
Não tivemos os problemas que lemos por aí como locks em bases de dados e o desempenho que obtivemos foi excelente. Montar um cluster com replicação de dados do tipo replica-set se mostrou um procedimento super tranquilo, assim como a configuração de sharding.
Se você tem estruturas de dados cujos atributos podem variar bastante de um elemento para outro em uma mesma coleção e não liga para redundância de informações, MongoDB se mostra uma solução muito interessante. Ele funciona.
Já sabia algum tempo atrás de algumas das suas limitações. É importante lembrar que limitação divulgada pelo fabricante não é defeito, mas sim característica. Uma limitação que surge “acidentalmente”, esta sim é um defeito. Aliás, na época cheguei a escrever sobre isto, alguns de vocês devem se lembrar. Aqueles pontos que falei em outubro de 2013 ainda se mantém (inclusive a versão em inglês deste site foi parar no Hacker News graças a este post).
Sobre desempenho a crítica que faço é sempre a mesma: benchmarks de internet não são válidos até que você tenha experiência no seu projeto. No nosso caso o que deu certo ocorreu por que satisfez dois requisitos.
- As estruturas de dados tinham atributos que realmente variavam bastante. Algo com atributos fixos não seria adequado. Além disto documentos embarcados eram uma alternativa interessante: redundância de dados não era um problema.
- Precisávamos de algo cujo tempo de escrita fosse o menor possível e sabíamos exatamente como estas estruturas deveriam se comportar.
Aonde estes dois requisitos se aplicavam, obtivemos sucesso.
E onde deu errado
Sabe estes dois requisitos que citei acima? São aonde vejo MongoDB funcionar perfeitamente até hoje nos projetos que passei. O principal problema foi causado por aquilo que mais temo: inércia mental.
Há aqueles momentos em que as pessoas estão tão habituadas com o modelo relacional que simplesmente não conseguem aceitar alguns fatos fundamentais sobre o MongoDB:
- Ele não foi feito para lidar com relacionamentos entre diferentes documentos. Documentos embarcados funcionam bem, mas quando você vai lidar com documentos em outras coleções, ou mesmo na mesma, o máximo que você tem é um quebra galho.
- MongoDB não foi feito para ter integridade referencial.
- Se os atributos da sua estrutura de dados são fixos e previsíveis, o registro é a melhor opção, não o documento.
- MongoDB não é uma base de dados relacional
- Não há uma implementação nativa de transações ACID entre documentos e nem era objetivo dos projetistas deste SGBD fazer isto.
Se seu sistema exige relacionamentos e integridade referencial por que não usar uma base relacional? Quer fazer bonito pra algum idiota? Use persistência poliglota! MongoDB e seu SGBD relacional favorito, cada um em seu galho. Por que não tirar o melhor dos dois mundos?
(implementar integridade referencial manualmente é muito triste)
Dicas
A seguir estão algumas dicas que ajudam bastante na adoção do MongoDB. Claro que há inúmeras outras, mas estas são as que considero mais importantes.
Use alguma biblioteca/framework de mapeamento
Uma boa opção é o Spring Data para MongoDB. O modo como lida com o mapeamento de relacionamento entre documentos é muito simples e próximo daquele que estamos acostumados a trabalhar com JPA.
(reparem na frase: “que estamos acostumados a trabalhar com JPA”. É a tentativa inconsciente de aproximar o MongoDB do modelo relacional! (ainda escrevo mais sobre isto no futuro))
Mas já lhe digo que o Spring Data para MongoDB não é perfeito: longe disto. Há bugs e limitações, mas o lado positivo é que se você abrir uma issue para a equipe de desenvolvimento do projeto e esta for bem descrita (dica: envie código reproduzindo o problema), eles resolverão rapidamente o problema. Quase todas as issues que abri foram atendidas em no máximo duas semanas, algumas na mesma semana de abertura.
Há outras alternativas também, como o Morphia, que funcionam muito bem, mas como nosso projeto era baseado em Spring, era mais interessante usar algo pertencente ao mesmo stack.
(ao que tudo indica o desenvolvimento do Spring Data está bem mais ativo também)
Conheça BEM o driver Java (ou da sua linguagem) do MongoDB
Estes frameworks de mapeamento quebram um bom galho mas há um preço: muitas vezes são lentos. Em aplicações que precisem de alto desempenho você irá observar que seu gargalo não estará no MongoDB, mas sim no código Java presente nestas bibliotecas.
Sendo assim, conhecendo bem o driver Java do MongoDB irá lhe ajudar horrores na hora em que precisar lidar com estes gargalos. Se seu sistema for basicamente CRUD, aí sim você pode ficar apenas com as bibliotecas.
Outro ponto fundamental é que pelo driver Java você consegue fazer praticamente qualquer coisa no MongoDB. Muitas vezes há um ou outro recurso que não está presente ainda na sua API de mapeamento favorita.
Precisa de transacionalidade entre documentos com MongoDB?
Se respondeu a sim esta pergunta e não quer usar uma base relacional, sua vida acaba de ficar difícil, mas não impossível. MongoDB oferece atomicidade em operações sobre um único documento, mas não entre documentos. Sempre tenha isto em mente.
Você pode implementar manualmente transacionalidade entre documentos, mas esta será bem limitada. No site do MongoDB há um tutorial que você pode consultar. O problema é que isto dá muito trabalho.
Vou falar sobre uma solução melhor para este problema mais a frente.
Não pensou no espaço que estes bancos de dados ocupam?
Yeap, eu já havia falado sobre isto antes. As bases de dados do MongoDB podem crescer bastante se você não ficar atento. Leve isto em consideração se não quiser levar um susto com o custo do seu storage. É sempre bom fazer algumas simulações do ambiente de produção antes de adotar o MongoDB: irá lhe poupar muito tempo, dinheiro e saúde.
Lembra aquela solução que havia prometido? Ei-la!
Considere seriamente a adoção do TokuMX ao invés do MongoDB
Sabia que o MongoDB tem um irmão gêmeo bem mais charmoso? Trata-se de uma distribuição alternativa chamada TokuMX: também é open source e é desenvolvido por uma empresa chamada TokuTek.
Bom: o que ele tem de bom?
- Resolve seu problema de espaço de armazenamento: uma de nossas bases no MongoDB ocupa 400Mb. No TokuMX? 15Mb.
- TokuMX implementa transação ACID entre documentos. Sim, você leu certo, e ela funciona MUITO bem.
- Apresenta desempenho bastante superior
E o melhor: 100% compatível. Se você trocar sua instalação MongoDB pelo TokuMX sua aplicação não notará diferença alguma além da melhoria de desempenho. Até este momento só vi dois poréns com o TokuMX:
- Ainda não há uma distribuição para Windows.
- Infelizmente as bibliotecas atuais não oferecem suporte nativo à implementação ACID do MongoDB: você terá de usar o driver nativo para obter este resultado. Existe uma issue no projeto Spring Data pedindo este suporte, mas não é prioritária ainda (mesmo eu pedindo :) ).
Treine BEM a sua equipe
Este é um ponto fundamental: você precisa expor para os membros do seu time o modo como devemos pensar a persistência fora do modelo relacional. É a única cura que conheço para o problema da inércia mental.
Conclusões
Estas foram minhas experiências com o MongoDB. Quanto mais cedo você detectar estas dificuldades que mencionei, melhor. Espero com este post ter dado minha contribuição. Devo confessar que até hoje a maior parte das reclamações que vejo sobre o MongoDB não são culpas da ferramenta, mas sim do seu mal uso.
E, pra finalizar MESMO: experimentem o TokuMX, é um produto muito superior e vai te poupar muito tempo. :)
Deixe uma resposta