NoSQL - Do teorema CAP para P?(A|C):(C|L)

NoSQL - Do teorema CAP para P?(A|C):(C|L)
steppat
steppat

Compartilhe

Existem muitas motivações para os bancos NoSQL, como por exemplo usar um modelo mais adequado para os seu dados ou facilitar alterações de schema; ou ainda além, melhorar o desempenho e simplificar a replicação para ter a tão sonhada escalabilidade linear.

O teorema CAP

Claro que todos os benefícios não vem sem custo, comparado com os bancos de dados tradicionais vamos perder alguma funcionalidade/garantia para ganhar outra. O tradeoff arquitetural é descrito no bem conhecido CAP theorem.

A palestra famosa do Dr. Eric Brewer introduz o teorema e explica que em qualquer sistema distribuído stateful é preciso escolher entre consistência forte (C - Consistency), alta disponibilidade (A - availability) e tolerância a particionamento dos dados na rede(P - Network Partition Tolerance). Segundo o teorema CAP, entre as três propriedades, somente duas podem ser garantidas ao mesmo tempo:

Partition-Tolerance

Poder particionar nossos dados em diferentes nós de um cluster é um dos recursos que aparecem com frequência nos bancos NoSQL. Saber lidar com a separação/particionamento das dados devido uma falha na rede é conhecido como Partition-Tolerant. No entanto, segundo o teorema CAP, em troca eles irão sacrificar a consistência forte ou a alta disponibilidade. Isso é diferente dos bancos tradicionais, que não possuem essa característica no design do sistema ou delegam isso para o filesystem.

NoSQL 1: Sistemas CP

Para sistemas que precisam da consistência forte e tolerância a particionamento (CP) é necessário abrir a mão da disponibilidade (um pouco). Pode acontecer, caso haja particionamento e o sistema não entre em consenso, que uma escrita seja rejeitada. Claro que os sistemas tentam evitar isso ao máximo, tanto que não costuma existir, por exemplo, uma transação distribuída e sim um protocolo de consensos para garantir a consistência forte. Exemplos desses sistemas CP são BigTable, HBase ou MongoDB entre vários outros.

NoSQL 2: Sistemas AP

Por outro lado existem sistemas que jamais podem ficar offline (24/7), portanto não desejam sacrificar a disponibilidade. Para ter alta disponibilidade mesmo com um tolerância a particionamento (PA) é preciso prejudicar a consistência (eventual-consistency). A ideia aqui é que os sistemas aceitam escritas sempre e tentam sincronizar os dados em algum momento depois (_read-consistency_). Então pode ter uma janela de inconsistência. Exemplos aqui são Amazon Dynamo, Cassandra ou Riak.

Sistemas CA

Os sistemas com consistência forte e alta disponibilidade (CA) (alta disponibilidade de um nó apenas) não sabem lidar com a possível falha de uma partição. Caso ocorra, sistema inteiro pode ficar indisponível até o membro do cluster voltar. Exemplos disso são algumas configurações clássicas de bancos relacionais.

Qual é a diferença entra CA e CP?

Vimos brevemente o teorema CAP e a escolha que os sistemas NoSQL fazem (CP ou AP) comparado com os bancos tradicionais (CA). É importante mencionar que para o desenvolvedor não haverá tantas diferenças entre CA ou CP. SEMPRE teremos consistência forte, no entanto, um sistema fica indisponível (CA) quando há particionamento - pois tem apenas alta disponibilidade por nó - e o outro sistema (CP) tente chegar a um consenso se aceita uma escrita ou não, que no pior dos casos também pode significar a indisponibilidade para uma parte dos dados. Seguindo desse raciocínio podemos perceber que a consistência e disponibilidade são extremos quando há particionamento. Isso foi uma dúvida que me incomodou bastante antes da minha palestra no Caelumday 2009. Podemos concluir que quando há particionamento (P) terá alta disponibilidade (A) ou consistência (C) forte: P?(A|C)

Mas o que acontece se NĀO há particionamento?

É uma pergunta que o CAP não responde. A primeira resposta poderia ser: claro que vai ser consistente já que ninguém gosta de lidar com dados desatualizados. Mas olhando para os sistemas NoSQL nem sempre isso é verdade. Existem sistemas que SEMPRE são eventually-consistent. Mas porque?

Consistência ou Latência

Há mais um motivo porque poderia fazer sentido sacrificar a consistência: O tempo da resposta ou a latência. Da mesma maneira que um sistema offline pode custar caro, um sistema lento também pode. Por isso pode fazer sentido abrir a mão da consistência para diminuir a latência.

De CAP para PAC/CL

O artigo do blog do Prof. Daniel Abadi explica o tradeoff com partições e sem. Ele sugere substituir a sigla CAP com PAC/CL (ou P?(A|C):(C|L)), traduzindo levemente modificado do artigo dele:

“... se há particionamento (P), o sistema pode valorizar a disponibilidade (A) ou a consistência (C), senão, quando o sistema roda sem partições, o sistema pode favorecer o tempo da resposta/latência (L) ou a consistência (C).”

Exemplos de PAC/CL

Seguindo dessa linha PC/C significa que o sistema valoriza a consistência sempre, com ou sem partições. Banco de dados tradicionais são sempre fortemente consistentes, ou seja PC/C. Amazon Dynamo ou Cassandra são sempre fracamente consistente, favorecendo a alta disponibilidade e o tempo da resposta (latência), ou seja PA/L. Mas existem misturas como o GenieDB (PA/C), que só trabalha consistente em caso de nenhuma partições. Quando há partições valoriza a alta disponibilidade. Exemplo contrário disso é o Yahoo Sherpa, que usa PC/L, ou seja com partições favorece consistência, sem partições diminuir a latência.

Durante o curso FJ-91, diversas questões e decisões arquiteturais são abordadas e discutidas, sendo que uma delas envolve o teorema CAP e os bancos de dados NoSQL.

Veja outros artigos sobre Programação