Introdução

Os bancos de dados conhecidos como NoSQL (Not only SQL) surgiram da necessidade de escalar bancos de dados para o resolver os problemas das aplicações web que operam em larga escala. NoSQL é um um termo genérico para uma classe definida de banco de dados não-relacionais que rompe uma longa história de banco de dados relacionais com propriedades ACID. Não podemos dizer que o NoSQL rompe o “império” dos bancos de dados relacionais. Os bancos de dados NoSQL servem para uma gama de problemas que nem sempre são os mesmos dos bancos de dados relacionais.

Arquitetura

Bancos de dados relacionais têm mostrado um desempenho ruim em certas aplicações com intensos fluxos de dados, incluindo a indexação de um grande número de documentos, servindo páginas em sites de alto tráfego, e entrega de streaming. Implementações típicas RDBMS são indicados tanto para pequenas, mas frequentes operações de leitura/escrita ou para transações de grandes lotes com poucos acessos de escrita. O NoSQL por outro lado, suporta pesados fluxos de leitura/gravação de dados.

Arquiteturas NoSQL costumam oferecer fracas garantias de consistência, como consistência eventual, ou transações restritas a itens de dados únicos. Alguns sistemas, no entanto, dão garantias ACID íntegras, em alguns casos, adicionando uma camada de middleware suplementar (por exemplo, CloudTPS) Dois sistemas são desenvolvidos para proporcionar o isolamento de instantâneo para armazenamentos de colunas. Estes sistemas, desenvolvidos de forma independente, utilizam conceitos para alcançar transações ACID multi-linha distribuídas com garantia de isolamento para o armazenamento de dados, sem a sobrecarga extra de gerenciamento de dados, implantação de sistema de middleware ou manutenção introduzida pela camada de middleware.

Vários sistemas NoSQL empregam uma arquitetura distribuída, com os dados armazenados de forma redundante em vários servidores, muitas vezes utilizando uma tabela hash distribuída. Desta forma, o sistema pode facilmente se expandir pela adição de mais servidores, e ser assim altamente tolerante a falhas em um servidor.

Alguns defensores do NoSQL promovem interfaces muito simples, como arrays associativos ou pares chave-valor. Outros sistemas, como bancos de dados XML nativo, promovem o apoio do padrão XQuery.

Escalabilidade

Quanto a arquitetura podemos dividir os bancos de dados NoSQL em dois tipos: distribuídos e não distribuídos. Os distribuídos tomam a responsabilidade pela partição dos dados e pela sua replicação.

Distribuidos

  • Amazon Dynamo
  • Scalaris
  • Voldemort
  • CouchDb (thru Lounge)
  • Riak
  • MongoDb (in alpha)
  • BigTable
  • Cassandra
  • HyperTable
  • HBase

Não distribuídos

  • Redis
  • Tokyo Tyrant
  • MemcacheDb
  • Amazon SimpleDb

Armazenamento

Podemos dividir os sistemas entre aqueles que armazenam dados em disco e os que armazenam na memória. Esta diferenciação é importante por que no caso da gravação em disco você vai precisar de um cache explicito. Já os dados armazenados em memória não são duráveis.

Memória

  • Scalaris
  • Redis

Disco

  • CouchDb
  • MongoDb
  • Riak
  • Voldemort

Configurável

  • BigTable
  • Cassandra
  • Hbase
  • HyperTable

Modelo de dados

Chave/Valor

  • Amazon Dynamo
  • Amazon S3
  • Redis
  • Scalaris
  • Voldemort

Documento

  • Amazon SimpleDb
  • Apache Couchdb
  • MongoDb
  • Riak

Colunas

  • Cassandra
  • Google BigTable
  • HBase
  • Hyperbase

Grafo

  • Neo4j
  • InfoGrid
  • Sones
  • HyperGraphDB

Exemplo Java (Apache Cassandra)

 <source lang="java">public class Teste {

/* * connect localhost/9160; * create keyspace javateste; * use javateste; * create column family autor; */

public static final String UTF8 = "UTF8"; static String columnFamily = "pessoa"; static Cassandra.Client client;

public static void main(String[] args) throws Exception {

TTransport framedTransport = new TFramedTransport(new TSocket("localhost", 9160)); TProtocol framedProtocol = new TBinaryProtocol(framedTransport); client = new Cassandra.Client(framedProtocol); framedTransport.open(); client.set_keyspace("javateste");

//insertRegistry(); //showColumnOfRegistry(); //showAllColumnsOfRegistrys(); showAllKeys();

framedTransport.close(); }

private static void showAllKeys() throws InvalidRequestException, UnavailableException, TimedOutException, TException { //todas as keys da familia SlicePredicate slicePredicate = new SlicePredicate(); SliceRange sliceRange = new SliceRange(); sliceRange.setStart(new byte[0]); sliceRange.setFinish(new byte[0]); slicePredicate.setSlice_range(sliceRange);

KeyRange keyRange = new KeyRange(); keyRange.setStart_key(new byte[0]); keyRange.setEnd_key(new byte[0]);

System.out.println("--KEYS--"); List<KeySlice> keys = client.get_range_slices(new ColumnParent("pessoa"), slicePredicate, keyRange, ConsistencyLevel.ALL); for(KeySlice ks : keys){ System.out.println(new String(ks.getKey())); }


}

private static void showAllColumnsOfRegistrys() throws InvalidRequestException, UnavailableException, TimedOutException, TException, UnsupportedEncodingException { // recuperar todas colunas de um registro na tabela System.out.println("--TODAS--"); SlicePredicate predicate = new SlicePredicate(); SliceRange sliceRange = new SliceRange(); sliceRange.setStart(new byte[0]); sliceRange.setFinish(new byte[0]); predicate.setSlice_range(sliceRange);

ColumnParent parent = new ColumnParent("pessoa"); List<ColumnOrSuperColumn> results = client.get_slice( stringToByteBuffer("1234"), parent, predicate, ConsistencyLevel.ALL); for (ColumnOrSuperColumn result : results) { Column column = result.column; System.out.println(new String(column.getName(), UTF8) + " -> "+ new String(column.getValue(), UTF8)); } }

private static void showColumnOfRegistry() throws UnsupportedEncodingException, InvalidRequestException, UnavailableException, TimedOutException, TException { // recuperar uma coluna de um registro try{ ColumnPath cp = new ColumnPath(); cp.setColumn("nome".getBytes()); cp.setColumn_family(columnFamily); ColumnOrSuperColumn col = client.get(stringToByteBuffer("2345"), cp, ConsistencyLevel.ONE); System.out.println("name: " + new String(col.getColumn().getName(), UTF8)); System.out.println("value: " + new String(col.getColumn().getValue(), UTF8)); System.out.println("timestamp: " + new Date(col.getColumn().getTimestamp())); }catch (NotFoundException e) { System.out.println("Nao encontrado"); } }

private static void insertRegistry() throws UnsupportedEncodingException, InvalidRequestException, UnavailableException, TimedOutException, TException { // inserir um registro com quaisquer colunas ColumnParent columnParent = new ColumnParent(columnFamily); ByteBuffer userIDKey = stringToByteBuffer("2345"); ConsistencyLevel consistencyLevel = ConsistencyLevel.ONE;

client.insert(userIDKey, columnParent, new Column(stringToByteBuffer("nome"), stringToByteBuffer("fulano"), System.currentTimeMillis()), consistencyLevel); client.insert(userIDKey, columnParent, new Column(stringToByteBuffer("idade"), stringToByteBuffer("30"), System.currentTimeMillis()), consistencyLevel); }

private static ByteBuffer stringToByteBuffer(String string){ return ByteBuffer.wrap(string.getBytes()); } }</source>


Mais Informações

http://nosql-database.org/

Pesquisadores

  • Elias José da Silva Alves