Por que eu devo ler este artigo:Uso de novas ferramentas e conceitos relacionados ao armazenamento de dados. Neste artigo é apresentado o noSQL, um movimento que engloba diversas ferramentas de armazenamento de dados não relacionais.

Ferramentas noSQL fornecem meios mais eficientes de armazenamento de grandes volumes de dados e/ou mecanismos de pesquisa de baixa latência, fatores importantes que precisam ser considerados durante a escolha de uma solução de armazenamento de dados.

Bancos de dados relacionais nem sempre são a melhor opção em cenários onde é necessário armazenar estruturas dinâmicas, tratar grandes volumes de dados ou lidar com estruturas não convencionais como grafos. Em contrapartida, as tecnologias noSQL oferecem diversas maneiras de tratar estes pontos, inclusive, de forma a trabalhar em conjunto com bancos de dados relacionais.

noSQL é um movimento que promove soluções de armazenamento de dados não relacionais. Ele é composto por diversas ferramentas que, de forma particular e específica, resolvem problemas como tratamento de grandes volumes de dados, execução de consultas com baixa latência e modelos flexíveis de armazenamento de dados, como documentos XML ou JSON.

As tecnologias noSQL não têm como objetivo substituir os bancos de dados relacionais, mas apenas propor algumas soluções que em determinados cenários são mais adequadas. Desta forma, é possível trabalhar com tecnologias noSQL e banco de dados relacionais dentro de uma mesma aplicação.

O termo noSQL é bastante abrangente, pois envolve diversas ferramentas, tecnologias, estruturas de dados e arquiteturas. Esta nova buzzword representa muito mais um movimento, ou uma nova escola de pensamento, do que alguma tecnologia em particular.

Escrever sobre este tema não é uma tarefa simples, pois além desta abrangência, é necessário lidar com dois pontos antagônicos: de um lado a desconfiança e o ceticismo sobre algo novo, do outro a excitação gerada por uma nova tecnologia.

Esta é a primeira parte de uma série de três artigos sobre noSQL, que irão apresentar, de forma consciente, clara e objetiva, o que de fato é noSQL. Neste artigo, será apresentado o conteúdo teórico, abordando os temas: história, modelos de dados alternativos ao relacional e arquitetura. Esta parte teórica é de extrema importância para compreensão do movimento como um todo, e fundamental para entender e nortear as escolhas das ferramentas classificadas como noSQL.

Um pouco de história

Antes de falar sobre noSQL, vamos entender um pouco da história dos sistemas de gerenciamento de dados desde seu surgimento até o aparecimento deste movimento chamado noSQL. Esta visão histórica é importante porque, como escreveu o filósofo George Santayana, “aqueles que não podem lembrar o passado, estão condenados a repeti-lo”.

Nos últimos 30 anos temos vivido a “ditadura” do modelo relacional, porém, é importante lembrar que os primeiros sistemas de gerenciamento de bancos de dados (ou SGBDs) não eram baseados em estruturas relacionais, e sim hierárquicas (IMS-DB, final dos anos 1960) ou baseados em grafo (CODASYL – anos 1970). O modelo relacional só seria apresentado por “Ted” Codd no início dos anos 1970 e realmente adotado apenas no final dos anos 1980.

Entretanto, após o modelo relacional ter se estabelecido, e sido largamente adotado, poucas iniciativas tentaram propor um modelo alternativo, e as poucas alternativas que surgiram não tiveram muito sucesso (como os bancos de dados orientados a objeto ou bancos xml).

Um ponto interessante e comum a cada nova proposta de modelos alternativos (isso desde o início, lá nos anos 1960) é a tentativa de invalidar e substituir por completo o modelo dominante, isso até agora...

O movimento noSQL

O movimento noSQL teve sua origem em junho de 2009, para nomear um encontro promovido por Johan Oskarsson e Eric Evans, que teve como objetivo discutir o crescente surgimento de soluções open source de armazenamento de dados distribuídos não relacionais. Em outubro do mesmo ano, foi realizada a conferência “no:sql(east)”, que redefiniu o uso do termo noSQL para descrever soluções de armazenamento de dados não relacionais.

Podemos considerar noSQL como uma nova onda de SGBDs, pois propõe algumas alternativas ao modelo relacional, porém com uma grande diferença histórica: o movimento noSQL não tem como objetivo invalidar ou promover a total substituição do modelo relacional, e sim o fim do modelo relacional como bala de prata, como a única solução correta ou válida. Inclusive, é importante entender que noSQL não significa “no SQL” (não ao SQL), mas sim “not only SQL” (não só SQL).

Com isso, temos, pela primeira vez na história, uma nova onda surgindo sem o objetivo de substituir por completo o modelo atual (relacional).

Nota: Ao que tudo indica o termo noSQL foi criado em 1998 por Carlo Strozzi para nomear seu projeto open source, que tinha como objetivo ser uma implementação mais leve de um banco de dados relacional, porém sua principal característica era não expor a interface SQL.

Portanto é bem irônico usar o termo noSQL, criado para nomear um banco de dados relacional, para classificar soluções de armazenamento de dados não relacionais.

Após esta importante visão histórica, iremos agora nos aprofundar nas características das soluções chamadas noSQL. Esta exploração será dividida em duas áreas distintas, porém complementares: Modelos de Dados e Características de Arquitetura. Vamos iniciar esta exploração pelos modelos alternativos ao relacional, pois esta é a porta de entrada para compreender melhor as propostas destas ferramentas noSQL.

Modelos de Dados Alternativos

Estamos habituados com o modelo relacional que é composto basicamente por tabelas, colunas e linhas, e que tem como principais características a integridade dos dados e a necessidade de modelar toda estrutura antes de seu uso (conhecido como schema-first).

Com o modelo relacional conseguimos, quase que naturalmente, modelar qualquer necessidade de armazenamento de dados, entretanto o modelo relacional nem sempre é o mais adequado para certas necessidades, como por exemplo: árvores (estrutura hierárquica) ou estruturas dinâmicas.

Atualmente, no universo de ferramentas noSQL, se destacam quatro diferentes tipos de modelos de dados: Chave-Valor, Orientado a Documento, Família de Colunas (ou clone de BigTable) e Grafo.

Nas próximas seções iremos explorar cada um destes modelos em detalhe, iniciando pelo mais simples, mas não menos poderoso: chave-valor.

Chave-Valor

A estrutura de dados do modelo chave-valor é muito parecida com a estrutura do java.util.Map, onde podemos armazenar uma chave e seu valor. Esse valor pode ser qualquer informação, ou seja, um blob.

Algumas ferramentas mais sofisticadas, como o Redis (que veremos mais adiante), além do blob permite armazenar como valor outras estruturas de dados, por exemplo: Listas Map<String, List<?>>, Sets Map<String, Set<?>> e até mesmo Hashes Map<String, HashMap<String, ?>>.

Uma característica importante do modelo chave-valor é que você pode pesquisar um dado apenas pela chave. Esta condição obriga o programador a elaborar muito bem suas chaves. Em contrapartida se obtém um comportamento O(1) no acesso aos dados, que na prática significa uma execução praticamente linear independente do volume de dados.

Nota: Blob - Forma de armazenamento de dados sem uma estrutura definida que permite armazenar um grande volume de dados.

Documento

Antes de falar sobre o modelo em si, é importante entender o que é um documento. O documento é uma estrutura de dados composta por uma quantidade variável de campos, com tipos de dados diversos, inclusive um campo pode conter um outro documento (chamado de sub documento). Muito complicado, muito abstrato? Simplificando: pense em um arquivo XML ou JSON como um documento, simples não?

Este modelo permite armazenar qualquer documento, sem ter a necessidade de definir previamente sua estrutura. Documentos podem ser armazenados em conjunto mesmo que não tenham nada em comum; este esquema é conhecido como schema-free. Outra característica do modelo de documento é a tendência de desnormalização dos dados, deixando em um só documento (ou “registro”) todas as informações relacionadas – inclusive as ferramentas que suportam este tipo de modelo são otimizadas justamente para isso.

Um exemplo de um modelo orientado a documento é a estrutura de um sistema de blog, onde em um único documento você pode (e deve) agrupar o post e seus comentários, veja o exemplo na Listagem 1.


  blog: {
    posts: {
      post: [ {
        id : 1,
        nome : 'Meu Primeiro Post!',
        texto : 'Aqui o conteúdo do meu post....',
        comentarios : {
          [ {
            id : 1,
            usuario : 'Anonym',
            texto : 'Muito Legal O post!'
          }, {
            id : 2,
            usuario : 'Anonym',
            texto : '#fail!'
          } ]
        }
      }, {
        id : 2,
        nome : 'Meu segundo post!',
        texto : 'Aqui.... o conteúdo deste meu segundo post....',
        comentarios : {
          {
            id : 1,
            usuario : 'Anonym',
            texto : 'não gostei deste texto.'
          }
        }
      } ]
    }
  } 
  
Listagem 1. Exemplo de Documento no formato JSON

Família de Colunas

O modelo de família de colunas se tornou popular através do paper BigTable do Google (publicado em 2006), com o objetivo de montar um sistema de armazenamento de dados distribuído, projetado para ter alta escalabilidade e suportar um grande volume de dados.

Este modelo é composto basicamente por três componentes: Keyspaces, Famílias de Colunas e Colunas, organizados conforme a Figura 1.

Estrutura do modelo de família de colunas
Figura 1. Estrutura do modelo de família de colunas

O Keyspace tem como função agrupar um conjunto de Famílias de Colunas. Este componente tem um papel parecido com um Database do modelo relacional.

Já o componente Família de Colunas tem uma estrutura mais próxima de uma tabela do modelo relacional, onde os dados são armazenados em linhas e organizados em colunas. Entretanto, as semelhanças param por aí, pois este componente tem suas próprias características, como o uso de uma chave única para identificação de cada linha e a quantidade variável de colunas, que traz flexibilidade ao modelo sem poluir as linhas com colunas nulas. A Listagem 2 mostra um exemplo, em formato JSON, de como os dados são organizados em uma família de colunas.


  Usuários = { // Usuários é o nome da Família de Colunas
    porcelli: [ // porcelli é a chave desta linha
      // colunas
      {coluna: "nome",    dados: [{timestamp: 123456789, valor: "Alexandre Porcelli"}]}, 
      {coluna: "email",   dados: [{timestamp: 123456789, valor: "porcelli@porcelli.com.br"}]}, 
      {coluna: "twitter", dados: [{timestamp: 123456789, valor: "@porcelli" }]}
    ],
    zezinho : [ // zezinho é a chave desta linha
      // colunas
      {coluna: "user",  dados: [{timestamp: 123456789, valor: "zezinho"}]}, 
      {coluna: "email", dados: [{timestamp: 123456789, valor: "zezinho88@gmail.com"}]}, 
      {coluna: "idade", dados: [{timestamp: 123456789, valor: "22" }]}, 
      {coluna: "sexo",  dados: [{timestamp: 123456789, valor: "masculino"}]} 
    ]
  }
  
Listagem 2. Exemplo de uma Família de Colunas utilizando o formato JSON

Por fim, temos a Coluna, que é uma tupla composta por nome, timestamp e valor, onde os dados são realmente armazenados. O elemento timestamp permite que uma única coluna armazene diversos valores, adicionando uma outra dimensão aos dados, como podemos ver no exemplo da Listagem 3.


{ // Esta coluna armazena todas as versões (histórico) de uma página html
  coluna: "conteudo_html",
  dados: [
    {timestamp: 123456789, valor: "<html><body><h1>Hello World
    </h1></html></body>"},
    {timestamp: 234567890, valor: "<html><body><h1>Good bye
    </h1></html></body>"},
    {timestamp: 345678901, valor: "<html><body><h1>Cruel World
    </h1></html></body>"}
  ]
}
Listagem 3. Exemplo de Coluna utilizando o formato JSON

Existem algumas variações do modelo de família de colunas, como por exemplo, a ferramenta Cassandra, que adiciona o componente Super-Coluna. A Super-Coluna é uma coluna especial que contém sub colunas, como mostra a Listagem 4.


  { // Super-Coluna
    nome: "endereço",
    // lista de Colunas
    valor: {
      // note que as chaves de acesso são os nomes das próprias colunas
      rua:    {coluna: "rua",    dados:[{timestamp: 123456789, valor: "rua xx 1234, ap 14 a"}]},
      cidade: {coluna: "cidade", dados:[{timestamp: 123456789, valor: "são paulo"}]},
      cep:    {coluna: "cep",    dados:[{timestamp: 123456789, valor: "05729-124"}]}
    }
  }
Listagem 4. Exemplo de Super-Coluna

Duas características adicionais e importantes deste modelo são a forma de consulta, que pode ser executada apenas através da chave das linhas de uma família de colunas, e a necessidade de definir previamente o conjunto de colunas que podem ser armazenadas em cada família.

O cenário típico de uso deste modelo está relacionado com a necessidade de lidar com grandes volumes de dados que precisam ser consultados com um tempo de resposta muito baixo, bem como a necessidade de armazenar uma estrutura de dados complexa (famílias compostas por diversas colunas). Alguns cases reais deste modelo são as aplicações Google Docs e Google Analytics, que utilizam o BigTable, e o Digg e Reddit, que utilizam o Cassandra.

Grafo

A melhor descrição sobre o modelo de grafos é de Marko Rodriguez (arquiteto de sistemas de grafo da AT&T Interactive): “Grafo é uma estrutura de dados que conecta um conjunto de vértices através de um conjunto de arestas. Os bancos de dados de grafo modernos suportam estruturas de grafo multi-relacionais, onde existem tipos diferentes de vértices (representando pessoas, lugares, itens) e diferentes tipos de arestas (como por exemplo amigo de, mora em, comprado por)[...]”.

Este é o modelo mais natural de representar dados, inclusive é conhecido como um modelo whiteboar d friendly (amigo do quadro-branco), pois conseguimos criar dados da mesma forma que desenhamos elementos e os conectamos através de linhas (com ou sem setas) em um quadro branco.

O exemplo mais comum utilizado para apresentar o modelo de grafo é a estrutura de dados de uma rede social, onde pessoas (que são representadas por vértices) conhecem ou seguem outras pessoas (os relacionamentos serão representados por arestas do tipo Conhece ou Segue). A Figura 2 mostra um exemplo de uma rede social entre alguns personagens do filme Matrix.

Exemplo de Grafo de uma rede
social
Figura 2. Exemplo de Grafo de uma rede social

Uma das características mais importantes deste modelo é a capacidade de navegar entre os relacionamentos (chamada de traverse) de forma linear – com comportamento O(1). A operação de traverse permite “descobrir dados escondidos” como: pessoas mais influentes em uma rede social, produtos mais comprados por determinado perfil, etc.

Depois desta introdução aos principais modelos de dados propostos pelos noSQL, iremos agora explorar algumas características de arquitetura destas soluções.

Arquitetura

Um dos pontos mais discutidos em torno do movimento noSQL é sem dúvida a parte arquitetural. No entanto, antes de aprofundar o tema arquitetura, é importante entender e refletir um pouco sobre como temos tratado o armazenamento de dados nos últimos tempos.

Como temos tratado nossos dados

No início, nós programadores Java, tínhamos apenas um recurso para acessar bases de dados, o JDBC – uma API padrão que nos permitia acessar qualquer banco de dados que disponibilizasse um driver (padrão jdbc). Mas quem programou usando JDBC puro sabe o quão trabalhoso era (a API faz uso extensivo de Checked Exceptions, o que torna o código bastante poluído).

A “salvação” veio com o surgimento de ferramentas de mapeamento objeto-relacional, chamadas de ORMs (object-relational mapping), que se popularizou graças ao Hibernate, e por consequência desta popularização, acabou influenciando na criação de uma API padrão de persistência, a JPA. Além de melhorar o nosso código, removendo muito código de infraestrutura, a JPA nos permitiu mapear POJOs (Plain Old Java Object) através de algumas anotações (ou, para o pessoal mais antigo, através de um arquivo XML).

As tecnologias de ORM trouxeram um ganho significativo de produtividade, contudo, para utilizar da melhor forma essa tecnologia, tivemos que abrir mão de algumas características do modelo relacional. Um exemplo disso é o banimento das chaves compostas (ou até mesmo as chaves naturais) em favor do uso de chaves artificiais. Do ponto de vista do desenvolvimento, faz todo sentido utilizar chaves artificiais (pois usar chaves compostas dá um trabalho muito grande quando usamos um ORM). Entretanto, quando começamos a propor isso aos ADs e DBAs, de cara foi rechaçado, pois estávamos “rasgando” o modelo relacional (lembre-se que os bancos de dados relacionais, além da parte relacional, são caracterizados pela integridade dos dados, e chaves compostas naturalmente forçam esta integridade). Após severas discussões, os desenvolvedores acabaram “ganhando”, pois conseguiram provar que seriam mais produtivos, e os DBAs e ADs também não saíram perdendo, pois poderiam criar constraints para implementar as regras de integridade.

Nota: Constraint - Recurso que permite adicionar uma regra a um ou mais atributos de uma tabela de um banco de dados relacional.

Dessa forma, manipular dados ficou muito simples, praticamente uma receita de bolo a ser seguida, o que nos levou a não nos preocupar mais com isso. No entanto, hoje vivemos a era do Big Data, onde um grande volume de dados é gerado a todo instante, e a manipulação deste volume começa a se transformar em um gargalo nos sistemas atuais. E devido à padronização do acesso aos dados através de ferramentas de ORM, acabamos nivelando a utilização dos recursos dos bancos de dados pelo menor denominador comum (até em favor de uma suposta “facilidade” de migrar de um fornecedor para outro, o que no final das contas quase nunca acontece), e este menor denominador comum, é claro, não inclui operações específicas para melhoria de performance ou a criação de padrões de acesso diferenciados.

O objetivo deste texto foi de apenas convidar você a refletir sobre como temos tratado o armazenamento de dados como um cidadão de segunda classe. E se existe um ponto a ser ressaltado com a buzzword noSQL, este ponto é: trazer o armazenamento de dados para o primeiro plano novamente, tratando o tema como um cidadão de primeira classe que exerce um papel fundamental na arquitetura de nossas aplicações.

Agora você deve estar se perguntando: por que é tão importante conhecer as principais características de arquitetura destas ferramentas noSQL? Para atingir certos objetivos, tais como, baixa latência, alta performance, escalabilidade ou um pouco de tudo isso, algumas ferramentas chamadas de noSQL tiveram que fazer escolhas de arquitetura nada ortodoxas, como por exemplo, abrir mão das propriedades ACID.

Nas próximas seções, vamos explorar algumas das principais características de arquitetura que devem ser analisadas quando avaliamos qualquer solução de armazenamento de dados, inclusive bancos de dados relacionais. Pois até bancos de dados relacionais têm características particulares; veja o caso do MySQL, ao utilizar o MyISAM (que ainda é o mais utilizado) você não terá uma solução totalmente ACID.

ACID vs BASE

Primeiro vamos deixar claro que as propriedades ACID (Atomicidade, Consistência, Isolamento e Durabilidade) são importantes, e todas as soluções de armazenamento de dados adorariam implementá-las, mas isso nem sempre é possível.

Implementar todas estas propriedades em uma solução distribuída e/ou de baixa latência é bastante complicado. Como mencionado anteriormente, até mesmo alguns bancos de dados relacionais não suportam todas as propriedades ACID em busca de performance e até mesmo simplificação de arquitetura. Existem diversos estudos sendo realizados em busca de equacionar estes pontos, porém ainda muito incipientes.

Então qual seria a alternativa ao ACID? Uma das propostas é o BASE (Basically Available, Soft-state, Eventual consistency), termo criado por Dan Pritchett que de forma elegante conseguiu jogar com as palavras e montar uma sigla para contrapor o termo ACID, gerando uma comparação entre Ácido vs. Básico.

Antes de falar sobre BASE, é importante entender a tradução do termo Eventual Consistency. Eventual é um falso cognato, ou seja, tem uma grafia similar em português porém com um significado diferente. Em inglês, eventual significa que irá ocorrer em algum momento, já em português eventual significa que pode ou não ocorrer. A melhor tradução para o termo Eventual Consistency que conheço é “Consistência em Momento Indeterminado”, feita por Maurício De Diana.

Agora, depois de entender melhor o sentido de eventual consistency, vamos retornar ao BASE. A ideia principal é abrir mão da consistência em favor da disponibilidade e escalabilidade. Entenda que abrir mão de consistência não quer dizer que seus dados estarão sempre inconsistentes, significa apenas que seus dados podem ficar inconsistentes por um pequeno período de tempo. Este período é relativo e depende de como sua aplicação foi desenvolvida e configurada, porém na maior parte do tempo o dado estará em estado consistente.

O sistema financeiro é repleto de situações onde BASE é utilizado. Um bom exemplo para entender o estado de inconsistência temporário é através da operação de transferência de valores entre bancos (DOCs ou TEDs). No momento da transferência o valor é debitado na conta do cliente que está enviando, porém este valor ainda não está na conta destino. Até o banco destino confirmar (ou recusar) a operação, o valor transferido não está em local algum e a conta do cliente que efetuou a operação está em um estado inconsistente. Após a confirmação (ou recusa) da operação do banco destino, os dados retornam ao estado consistente.

Em resumo, em sistemas ACID o dado é modificado de estado consistente para consistente a cada operação, já no BASE os dados estão em estado de fluxo, isto é, em constante modificação.

Para finalizar, vamos deixar claro que existem ferramentas noSQL com propriedades ACID, um exemplo é o Neo4j.

Modelo de Persistência

Grande parte dos bancos de dados relacionais atuais tem como meio de persistência principal o disco, o que, em conjunto com logs e outras técnicas, são capazes de oferecer garantia de durabilidade dos dados (ou seja, uma vez os dados commitados eles se tornam permanentes). Este é o modelo tradicional. Entretanto, é importante lembrar que o acesso ao disco tem um custo muito alto de IO. Soluções que necessitam de baixa latência em geral não se adequam a este meio de persistência.

Apesar disso, existem algumas técnicas que visam minimizar o custo de IO com o disco. Uma delas é a utilização de arquivos memory-mapped, ou seja, um meio de mapear uma parte da memória diretamente a um arquivo do disco, então, uma vez criado este mapeamento, as operações executadas na memória são refletidas no arquivo. Esta técnica aumenta significativamente a velocidade de acesso aos dados, entretanto seu uso acarreta alguns problemas. O principal deles é o risco de perda de dados que pode ser causado por uma corrupção no arquivo, ocasionado por um crash na máquina (ex: falta de energia). Ferramentas que utilizam esta técnica aconselham replicar os dados em mais de uma máquina, para diminuir o risco de perda de dados.

Mas o disco não é o único local onde podemos alocar dados. A memória é um local quase perfeito para “armazenar” dados. Com ela conseguimos obter o menor nível de latência, e nos dias atuais não é difícil encontrar servidores com 32GB ou até mesmo 64GB de memória – para algumas aplicações esta quantidade de memória é suficiente para alocar praticamente todo o banco de dados. Algumas ferramentas noSQL utilizam a memória como seu principal meio de “persistência”, utilizando o disco como uma forma secundária, fazendo serialização em disco através de uma thread paralela.

Infelizmente a memória é volátil, ou seja, se a máquina for desligada, ou até mesmo se ocorrer uma falha na aplicação e ela for finalizada, você perderá todos os dados. Por outro lado, tenha em mente que o ambiente computacional atual (seja em datacenters privados ou em grandes estruturas de cloud computing) é capaz de gerar um uptime de máquina próximo de 99,999%.

Como podemos observar, cada meio de persistência tem vantagens e desvantagens. É nossa obrigação, desenvolvedores e arquitetos, escolher o modelo que melhor atende às necessidades de nossas aplicações.

Padrão de Manipulação de Dados

No mundo relacional estamos acostumados a utilizar comandos SQL (insert, delete, update e select) para a manipulação dos dados, porém quando falamos de noSQL, como você pode imaginar, esta interface não existe. Então como manipular dados? Através de APIs! Em geral as APIs destas ferramentas são bem simples de usar, apesar de não existir nenhum padrão entre elas. Portanto, ao adotar qualquer ferramenta noSQL tenha em mente que você irá abrir mão de qualquer tipo de padronização, mesmo entre ferramentas que tratam o mesmo tipo de modelo de dados.

Outro ponto relevante a ser compreendido é o modelo de busca dos dados. Grande parte das ferramentas noSQL permitem apenas a busca de dados por uma única chave ou através de views previamente definidas – são raras as ferramentas que permitem criar consultas ricas ad-hoc.

Ainda sobre padrões de manipulação de dados, é importante entender qual é o perfil de sua aplicação em termos de intensidade de leitura e/ou escrita. Esta compreensão poderá facilitar ou nortear a escolha da melhor ferramenta.

Modelo de Distribuição

Para manter um ambiente de alta disponibilidade não podemos confiar apenas em uptime e simplesmente delegar esta atividade à equipe responsável pela infraestrutura. Como desenvolvedores temos que criar uma arquitetura onde não exista um único ponto de falha, que seja capaz de mitigar os riscos de uma aplicação ficar fora do ar. Para isso existem algumas técnicas, e uma das mais comuns é a distribuição e replicação dos dados em mais de uma máquina (dependendo das necessidades de SLA de sua aplicação, isso pode envolver diferentes data centers distribuídos em diversas localizações geográficas).

Para implantar este cenário é fundamental entender quais são os recursos que sua ferramenta de armazenamento de dados disponibiliza, tais como replicação master/slave ou até master/master. Contudo, além de conhecer e utilizar um processo de distribuição e replicação, também é fundamental conhecer seu comportamento em caso de falha de alguma máquina (seja ela a master ou a slave).

Compreender como se dá todo o processo de recovering é muito importante, pois tudo funciona muito bem na documentação ou em exemplos disponíveis em posts na web. Porém, na vida real é um “pouco” diferente, e a melhor forma de saber como efetivamente todo este processo ocorre é através de testes reais e benchmarks, de preferência com os dados de sua aplicação, para comprovar o funcionamento de cada ferramenta no seu ambiente.

Existem ainda ferramentas que oferecem o particionamento automático dos dados, que nada mais é do que a capacidade de dividir e distribuir os dados de uma grande base para bases menores em diversas máquinas.

Nota: Particionamento de Dados - Técnica bastante popular para obter escalabilidade horizontal em bancos de dados relacionais. Particionar dados consiste em dividir um grande banco de dados em bancos de dados menores independentes. Para esta divisão é utilizado algum fator, por exemplo, a letra inicial do nome do usuário. Assim, usuários iniciados em A até D ficam no servidor 1, usuários de E até K no servidor 2 e assim por diante.

Um dos problemas desta técnica em modelos relacionais é a necessidade de deixar de usar chaves estrangeiras em determinados relacionamentos, o que pode levar a base a um estado inconsistente. Em bancos não relacionais como chave-valor, documento ou família de colunas, esta técnica não tem impactos negativos, uma vez que não existe relacionamento no modelo.

Já para o caso do modelo de grafo, aplicar esta técnica não é nada fácil, pois os nós e links são criados de forma dinâmica e altamente acoplados, tornando o particionamento de dados uma tarefa muito complicada.

Escalabilidade e Elasticidade

Quando precisamos tratar grandes volumes de dados (o chamado Big Data), precisamos ter a capacidade de criar clusters não só para nossos servidores de aplicação, mas também para as nossas ferramentas de armazenamento de dados.

Apesar de grande parte das ferramentas de bancos de dados relacionais oferecer algum mecanismo de escalabilidade horizontal, o modelo relacional se comporta melhor em um modelo de escalabilidade vertical. Em contrapartida, algumas ferramentas noSQL têm seu comportamento planejado para trabalhar de forma mais otimizada em escala horizontal (exemplo: Cassandra).

Outro ponto importante quando falamos de escalabilidade horizontal (ou cluster) é sua elasticidade, ou seja, a capacidade de adicionar, de forma “transparente”, novas máquinas ao sistema – preferencialmente sem a necessidade de reiniciá-lo (exemplo: Riak).

Claro que existem outros fatores que devem ser considerados quando adotamos uma tecnologia, tais como: maturidade, cases de sucesso, estabilidade e, principalmente, a capacidade da equipe de absorver esta tecnologia.

Nota: Escalabilidade Vertical e Horizontal - A escalabilidade vertical consiste em adicionar mais poder de processamento, memória ou disco em uma máquina, já a escalabilidade horizontal é a capacidade de adicionar novas máquinas para, de forma distribuída, aumentar os recursos de processamento, memória e disco.

Em favor da escalabilidade vertical tem sua simplicidade, pois inicialmente é mais simples adicionar mais hardware sem ter que modificar o software. No entanto, em algum momento o custo do hardware pode se tornar impeditivo, ou em casos extremos atingir o limite.

Já a escalabilidade horizontal tem como maior vantagem a capacidade de expansão linear, pois sempre é possível adicionar novas máquinas. Entretanto, criar sistemas para trabalhar de forma distribuída é bem mais complexo.

Conclusão

Então o que é noSQL? Como pudermos ver ao longo deste artigo, responder esta pergunta não é nada fácil, pois é um movimento que engloba diversas ferramentas que implementam novas estruturas de dados e arquiteturas.

No entanto, podemos definir noSQL como o fim dos bancos de dados relacionais como bala de prata, estimulando a escolha de ferramentas que melhor se adequem às necessidades de nossas aplicações.

A maior contribuição do movimento noSQL foi trazer à tona um componente arquitetural importante e que estava sendo negligenciado, o modo como armazenamos e tratamos nossos dados.

Na segunda parte deste artigo será apresentado na prática como instalar e utilizar as principais ferramentas noSQL disponíveis, de forma a abranger os modelos de dados e arquiteturas apresentados nesta primeira parte.

Confira também