Arquivo do autor:Fernando Melo

Sobre Fernando Melo

Fernando Melo é cientista da computação especializado em Data Management, e é apaixonado pelas tecnologias que mudam positivamente a vida das pessoas. Atualmente trabalha como Engenheiro de Solução para a Área de Gestão de Dados, e escreve este blog. Você pode segui-lo no Twitter / Instagram / Facebook @fmelodb e YouTube no canal Universo dos Dados. Nota: os textos e interesses neste blog refletem minha opinião pessoal, e não necessariamente representam as visões do meu empregador.

OCI NoSQL Tables

Geralmente temos servidores e storage, e então bancos de dados, e claro, tabelas. No entanto, com o avanço das arquiteturas cloud native existe uma outra abordagem: as tabelas sem bancos de dados e sem servidores (tabelas serverless).

Essas tabelas existem como um serviço gerenciado em diversos provedores de cloud, e somente nos provedores de cloud, pois elas são uma consequência das arquiteturas cloud native. Neste post vou escrever sobre o serviço NoSQL Tables, as tabelas Serverless da Oracle Cloud (OCI).

Vou explicar como elas funcionam, para que servem, casos de uso, e também vou mostrar um exemplo prático para ficar mais claro.

Principais Características

Apesar de você não enxergar os servidores, eles existem, claro! Mas o serviço expõe as tabelas com uma abordagem serverless. Do ponto de vista físico, as NoSQL Tables são tabelas que implementam o conceito de sharding, isto é, os dados são distribuídos de forma horizontal em servidores diferentes. Além disso, os dados de cada servidor também são replicados para outros servidores. Essa arquitetura distribuída, além de promover alta disponibilidade e durabilidade, garante que o tempo de resposta seja, sempre de forma estável e previsível, de poucos milisegundos.

Como os dados são distribuídos e replicados em servidores diferentes, você pode escolher se as leituras serão do tipo consistente ou eventual, e se vai utilizar ACID para as transações: para entender melhor este ponto (caso não conheça), veja este meu outro post onde abordo o Teorema CAP.

Há bastante flexibilidade para escolher o formato dos dados: existe suporte para dados em colunas (schema-full), tal como conhecemos no modelo relacional (ex: integer, string timestamp e Blob), mas adiciona tipos complexos, como Arrays, Records e Map. E claro, não menos importante, também suporta JSON nativamente (schema flexível).

Outras capacidades que também ajudam bastante em diversos casos é a possibilidade de configurar TTL (time-to-live, onde os dados são removidos automaticamente após o tempo que você especificar), criação de índices secundários (inclusive com JSON), e também a possibilidade de usar SQL ou API (com suporte a Spring Data).

Como não existe servidor, e se quer existe um banco de dados (pelo menos em termos de usabilidade), como será que esses serviços são dimensionados? Bom, aqui está a grande diferença: pelo workload! Isto é, você dimensiona uma NoSQL Table informando qual é a demanda de uso.

São três variáveis requeridas quando se cria uma NoSQL Table na OCI:

  • Quantidade máxima de leituras por segundo;
  • Quantidade máxima de escritas por segundo;
  • Espaço em Gbytes.

Essas variáveis podem ser alteradas de forma online enquanto a tabela existir (elástico, para cima ou para baixo, a qualquer tempo).

Nota: o billing deste serviço considera essas três variáveis: existe um preço por read unit, outro para write unit, e outro para gbytes utilizados. Em geral é um serviço considerado barato, e faz parte do free tier, mas é importante estimar o custo para o seu workload.

No final do dia NoSQL Tables é um serviço gerenciado, então operações como provisionamento de infraestrutura, backup, patching, configurações de alta disponibilidade e segurança, enfim, tudo aquilo que é necessário para deixá-lo no ar e disponível é gerenciado pela própria OCI.

Casos de Uso e Utilidade

Por ser simples, permitir um schema flexível, com baixa latência previsível, e ser completamente gerenciado, as tabelas serveless podem ser bastante úteis nos casos de uso abaixo e quaisquer outros casos similares a estes:

  • Perfis de usuário;
  • Eventos de qualquer tipo (usuários, clicks, etc) e IoT;
  • Carrinho de compras;
  • Catálogo de produtos;
  • Cache de dados para web servers;
  • Armazenamento de metadados e parâmetros;
  • Personalização de anúncios;
  • Detecção de fraude em tempo real.

Claro que existem também os casos onde elas não são úteis. Vou colocar abaixo os principais casos onde você deve fugir das tabelas serverless:

  • Migrar um banco de dados legado existente as-is (a não ser que você queira fazer um grande refactoring);
  • Necessita de um modelo de dados mais complexo, que demanda por um schema com muitas tabelas e relacionamentos. Se não for possível colocar tudo em poucas tabelas, ou se não for compatível com workloads do tipo JSON, não use;
  • No caso onde os limites do serviço gerenciado são insuficientes para o seu caso de uso. À propósito, isto vale para qualquer serviço gerenciado.

Na Prática

As NoSQL Tables podem ser usadas de diversas formas: pelo console gráfico da OCI, pela CLI (Command Line Interface), e também pelas SDKs nas diversas liguagens suportadas, como Java, Node.js, Python, .Net e Go.

Vou utilizar a CLI para criá-las, e para isso você precisa configurar a OCI CLI previamente.

Nota: no arquivo de configuração da OCI CLI você pode colocar alguns parâmetros que utiliza com frequência para evitar de repeti-los toda vez que faz uma chamada CLI. Nos exemplos a seguir eu fiz isso para o parâmetro compartment_id, que é obrigátorio e é responsável por agrupar logicamente os recursos que você cria na OCI).

Com a CLI configurada, veja abaixo como é simples criar uma tabela serverless na OCI. Primeiro vamos especificar os limites da tabela, criando este arquivo table_limits.json:

{
  "maxReadUnits": 2,
  "maxStorageInGBs": 1,
  "maxWriteUnits": 2
}

Com este arquivo como exemplo, nossa tabela permitirá no máximo 2 leituras (maxReadUnits) e 2 escritas (maxWriteUnits) concorrentes, e até 1 GByte de espaço (maxStorageInGBs).

Depois podemos utilizá-lo no comando abaixo:

oci nosql table create --ddl-statement "CREATE TABLE usuarios (id integer, nome string, PRIMARY KEY (SHARD(id)))" --name usuarios --table-limits file://table_limits.json

A tabela chama-se Usuarios, e coloquei apenas duas colunas: id (integer) e nome (string), onde id é a chave primária, e também é a coluna que distribui os dados horizontalmente (shard).

Se eu quisesse utilizar JSON para a coluna nome, bastava substituir string por json na criação da tabela, ou ainda adicionar mais colunas de outros tipos.

Para listar suas tabelas criadas, você pode executar o seguinte comando:

oci nosql table list

Este comando vai retornar um output JSON com a lista de tabelas e suas propriedades.

Apesar de eu não achar apropriado, podemos também manipular e consultar dados pelo OCI CLI. Este comando abaixo insere um registro:

oci nosql query execute --statement "INSERT INTO usuarios (id, nome) VALUES (1,\"Fernando\")"

É possível consultar a tabela com SQL, utilizando este comando:

oci nosql query execute --statement "SELECT * FROM usuarios"

Para remover a tabela, você pode fazer desta forma:

oci nosql table delete --table-name-or-id usuarios

Bom, utilizar a OCI CLI para criar e remover tabelas tudo bem, mas para manipular dados com certeza é melhor utilizar alguma SDK, pois é através dela que você utilizará as tabelas serverless no seu sistema.

Vou utilizar como exemplo a SDK em Python. Veja aqui os requerimentos para instalar os drivers (biblioteca borneo) no seu sistema.

Abaixo vou fazer uma consulta simples pela chave usando API, mas antes preciso importar a biblioteca com os objetos que usaremos, e também fazer a configuração de conexão e autenticação:

from borneo import NoSQLHandle, NoSQLHandleConfig, Regions, Consistency
from borneo.iam import SignatureProvider

handleConfig = NoSQLHandleConfig(Regions.US_ASHBURN_1)
config = handleConfig.set_authorization_provider(SignatureProvider())
config.set_default_compartment('dev')
config.set_consistency(Consistency.EVENTUAL) # ou Consistency.ABSOLUTE
conn = NoSQLHandle(config)

Importei da biblioteca borneo (que utilizamos para manipular as NoSQL Tables) todos os objetos que vou utilizar nos exemplos seguintes.

config é minha configuração de conexão e autenticação, que recebe a região da OCI que usei para criar a tabela (us_ashburn_1) e meus dados de acesso com SignatureProvider(): esse método retorna minhas credenciais que estão configuradas na minha OCI CLI — há várias outras formas de autentição também, veja aqui.

dev é o compartimento onde criei a tabela, e Consistency.EVENTUAL configuro as leituras para serem eventuais (Availability + Partition Tolerance, do Teorema CAP), mas poderia configurar como Consistency.Absolute (Strong Consistency + Partition Tolerance, do Teorema CAP).

O objeto conn (criado a partir de config) é utilizado para as demais operações sobre a tabela.

Bom, vamos então para a consulta simples pela chave usando API:


from borneo import GetRequest

request = GetRequest().set_table_name('usuarios')
request.set_key({'id': 1}) 
result = conn.get(request) 
if result.get_value() is not None:
    print(result)   

Primeiro informei no objeto request qual é o nome da minha tabela, e depois consigo consultá-la informando qual é a chave de busca pelo método set_key. O objeto result recebe o resultado da consulta.

O código abaixo faz a mesma coisa, porém utiliza SQL, e Prepared Statements:

from borneo import QueryRequest, PrepareRequest

sql = 'declare $myKey integer; select * from usuarios where id = $myKey'
request = PrepareRequest().set_statement(sql)
prepStmt = conn.prepare(request).get_prepared_statement()
prepStmt.set_variable('$myKey', 1)
queryRequest = QueryRequest().set_prepared_statement(prepStmt)
while True:
    result = conn.query(queryRequest)
    resultList = result.get_results()
    if queryRequest.is_done():
        break

print(resultList)

PreparedStatements servem para otimizar a execução das instruções SQL em um banco de dados, de forma que faça apenas um parse e múltiplas execuções (ao invés de fazer um parse para cada execução).

Inicialmente criei uma string SQL utilizando $mykey como variável. Depois preparei o statement, e depois fiz a operação de bind, que é colocar o valor na variável $mykey. Por fim a query é executada e o resultado é atribuído ao objeto resultList.

E quanto as transações? Certo! É possível inserir, atualizar e remover dados, normalmente.

Veja abaixo como faço para inserir mais um registro na minha tabela:

from borneo import PutRequest

request = PutRequest().set_table_name('usuarios')
request.set_value({'id': 2, 'nome': 'Paulo'})
result = handle.put(request)
if result.get_version() is not None:
   print('success')

Basta criar um request utilizando o objeto PutRequest, atribuir o valor, e executar com put. Também é possível fazer com SQL, e também é possível fazer várias mudanças com uma simples operação (WriteMultipleRequest).

Neste post eu fiz um overview bem resumido do que é possível fazer com as tabelas serverless. Em outros posts vou mostrar outras capacidades deste serviço. Stay tuned!

Conclusão

As NoSQL Tables são mais robustas do que parecem. Você pode criar tabelas serverless com múltiplos formatos, incluindo JSON e SQL (com ACID e opção de escolha entre consistência forte ou eventual), índices secundários e TTL. É muito fácil de começar, e não há muito o que aprender, pois o serviço é totalmente gerenciado.

Referências

Você pode me seguir neste blog:

Disclaimer: As opiniões expressas neste blog são minhas, e não são necessariamente as mesmas opiniões do meu empregador.


Change Data Capture

CDC é um padrão de integração de dados que vem se tornando cada mais vez mais comum hoje em dia. CDC significa, do inglês, Change Data Capture: uma tradução direta para o português seria Captura de Dados Alterados.

Em resumo, uma ferramenta que suporta CDC é capaz de capturar os dados de uma origem no momento em que estes são criados ou alterados, e os transportam para um destino, com baixa latência.

Há dois grandes benefícios neste tipo de integração:

  • O primeiro é a velocidade com que os dados são propagados da origem para o destino (near real-time, baixa latência);
  • O segundo é a heterogeneidade, uma vez que as ferramentas de CDC geralmente permitem capturar em um formato (plataforma, tecnologia, máquina, etc) e entregar em outro completamente diferente.

Atualmente CDC é usado em arquiteturas de microsserviços (em especial para capturar dados de sistemas legados, e também para endereçar alguns padrões como CQRS e Event Sourcing), e também, majoritariamente, em arquiteturas de integração de dados.

Sabemos que integração de dados é um processo que utilizamos para mover dados de um lugar para outro. Normalmente os dados são movidos de sistemas transacionais para repositórios centrais de dados, como os Data Warehouses, Data Lakes ou Lakehouses. Esses repositórios centrais oferecem melhor capacidade para a análise de dados através da utilização de técnicas de consumo, como mineração de dados, machine learning, e data visualization.

Bom, mas nem tudo são flores. Geralmente as empresas possuem muitos sistemas transacionais, e cada um com suas próprias complexidadades. E por isso, nem todas as integrações são realizadas da mesma forma. Cada integração é criada de acordo com as características de cada sistema, das capacidades deles de permitir que os dados sejam capturados. Algumas tabelas de um banco de dados, por exemplo, podem não oferecer colunas de timestamp ou algum identificador para capturarmos as mudanças de forma incremental, ou o sistema não possui APIs que expõem seus dados, ou eventualmente eles têm tudo, mas você não pode tocar neles porque as integrações podem impactar no desempenho do sistema. CDC resolve esses problemas.


Você pode ver este conteúdo em video pelo meu canal Universo dos Dados, no YouTube:


Velocidade e Desempenho

Nós temos a disposição geralmente três formas de lidar com a velocidade (latência de entrega dos dados) em uma integração: snapshot, batches incrementais e CDC – e cada uma dessas formas produz um tipo de impacto de desempenho na origem onde os dados são capturados:

  • O primeiro deles, snapshot, é o mais simples, e o pior (mais lento) deles. Snapshot é como uma foto em um ponto no tempo. Você pode buscar os dados, por exemplo, todo dia à meia-noite. O método de snapshot sempre vai trazer tudo, e por isso, quanto maior a quantidade de dados, mais tempo para trazê-los, mais tempo de impacto na origem (concorrência de leitura), e maior consumo de espaço no destino.
  • Batches incrementais são um pouco melhores do que o snapshot. Com esta abordagem você vai sempre trazer as diferenças desde o último batch incremental. O período de execução do batch incremental pode ser 1 vez por dia, 1 vez por hora, ou 1 vez a cada 15 minutos, por exemplo. Ou seja, você não precisa trazer todos os dados todas vezes. No entanto, um trade-off desta abordagem é que você acaba perdendo os deletes que ocorrem, pois ele retorna uma foto da diferença, desta forma dados removidos nunca aparecem nesses snapshots incrementais. Além disso, é preciso endereçar bem como as mudanças são capturadas, pois é necessário fazer consultas com filtros utilizando algum timestamp ou identificador, em especial de forma indexada, e isso pode eventualmente impactar no desempenho na origem.
  • Por fim, CDC é a terceira abordagem, e ao contrário das anteriores, é a maneira que oferece a melhor velocidade, e o menor impacto da origem.

Geralmente as ferramentas que implementam CDC suportam os seguintes tipos de origens (source) e destinos (targets): bancos de dados, filesystems, APIs e brokers de eventos (streams).

O mais comum deles são os bancos de dados: as mudanças são capturadas do log de transação deles (que praticamente todos os bancos de dados têm), isto é, cada vez que há uma alteração em um banco de dados, essa alteração é escrita no log, e imediatamente a ferramenta de CDC captura deste log e propaga os dados para o destino. Também dizemos que o mecanismo de captura dos dados em bancos de dados é chamado de push (empurrar), pois literalmente as mudanças de estado nos dados são empurradas nos arquivos de log das transações.

Desta forma, dizemos que o padrão de integração CDC possui uma velocidade near real-time.

Infelizmente, todos os outros tipos de origens suportados por ferramentas de CDC não são tão amigáveis como são para os bancos de dados, pois estes outros não possuem arquivos de log de mudanças/transações – dizemos que eles são do tipo pull (puxar), isto é, tem que ir lá e pegar/puxar de tempos em tempos. Arquivos em filesystems precisam ser copiados a cada busca; APIs e broker de eventos (streams) tem um perfil mais micro-batch incremental do que propriamente CDC.

De qualquer forma, com a popularização do CDC, muitas ferramentas estão cada vez mais oferecendo algum tipo de melhoria e logs para serem suportados pelo padrão de integração CDC do tipo push.

Heterogeneidade

A heterogeneidade é um dos grandes benefícios do CDC. Eles são capazes de capturar e entregar dados para tecnologias diferentes, sem precisar de qualquer área intermediária (stage) para conversão.

Então você pode capturar dados de um banco de dados relacional, e entregá-los a um filesystem em formato JSON. Capturar dados de uma fila de mensagens, e entregá-los a um banco de dados. Capturar dados do Hive e entregar para um Kafka, e assim por diante.

Claro que eventualmente conectores são necessários nas pontas para fazer algum tipo de conversão, mas a capacidade de lidar com origens e destinos de forma heterogênea, entregando os dados com extrema baixa latência, é um diferencial deste padrão de integração.

Quando Usar

Abaixo eu listo alguns dos principais casos de uso onde CDC tem bastante valor:

  • Migrações de plataformas e sistemas: migrar dados de um sistema legado, como um mainframe, para uma plataforma mais moderna (JSON, REST, Microsserviços, Cloud, etc). Migrar plataforma com CDC permite desacoplar o antigo do novo. Em outras palavras, é possível conviver com ambas as plataformas ao mesmo tempo sem precisar de uma migração big bang. Mudanças realizadas no sistema novo são propagadas para o sistema antigo, e vice-versa.
  • Carga em tempo real para Data Warehouses: com CDC você captura as mudanças de dados dos sistemas transacionais e já as entrega para o DW, em near real-time. É a letra E do ETL feita de uma forma não-batch. O CDC permite que o DW seja atualizado praticamente a todo tempo, e por isso essa capacidade habilita a disponibilização dos dados para suporte à decisão em tempo quase near real-time.
  • Atualizações de caches e índices: você pode manter um cache atualizado no Redis (ou qualquer outro mecanismo de cache ou data grid), e atualizar um Search Index no ElasticSearch, por exemplo, na medida que os dados são alterados em uma fonte de dados transacional.
  • Atualização de tabelas read-only em Microsserviços: nas arquiteturas de microsserviços, onde geralmente cada serviço tem seu próprio banco de dados, o correto seria um serviço chamar uma API de outro para obter seus dados, mas nem sempre isso é possível, e pode gerar problemas de desempenho. Manter uma réplica read only em bancos de dados de outros serviços, sincronizados por meio de CDC, pode melhorar bastante a performance e ainda assim manter as características de disponibilidade e autonomia dos microsserviços.
  • Sincronizar dados em cloud híbrida e multi-cloud: CDC permite sincronizar dados em serviços de dados que existem em clouds diferentes, ou mesmo entre serviços cloud e recursos on-premises. Um exemplo bastante comum é criar um ambiente de disaster recovery em cloud, a partir dos dados que existem on-premises.

Principais Tecnologias

No momento que escrevo este post existem algumas ferramentas de CDC bastante comuns no mercado.

Na esfera comercial, o principal deles, o mais robusto e sofisticado é o GoldenGate, da Oracle – este também disponibilizado como um serviço gerenciado na Oracle Cloud.

Na esfera open-source, o principal deles é o Debezium, comumente usado em vários casos de uso com Apache Kafka.

Há outras ferramentas no mercado que suportam o padrão de integração CDC, não como uma ferramenta de CDC em si, mas como uma capacidade complementar. Uma delas é o Airbyte por exemplo, que é como tantas outras uma ferramenta de Integração de Dados que suporta, também, CDC.

Conclusões

Considere o padrão de integração CDC sempre que precisar que os dados sejam capturados em near real-time.

Você pode me seguir neste blog:


Transformação Digital, sem Buzzwords

1. Seus ambientes não-produtivos são efêmeros, e você os recria do zero todo dia. Quando precisa. Quanto precisa. Por código. Imediato.

2. Você não move seus dados nunca. Todos eles são necessariamente virtualizados e convergidos, acessados sempre com a mesma interface. Não importa o formato, o tamanho, e a velocidade.

3. Zero ETL. Real-time analytics, sempre.

4. Criptografia por padrão em qualquer coisa: in-flight, in-memory, e at rest.

5. Mudanças em produção ocorrem a todo tempo, sem parada.

6. Sua capacidade escala do zero ao máximo, por segundo. Sem interrupção. O máximo é ilimitado.

7. Data Lineage de tudo que você tem com no máximo dois cliques de esforço.

Arquitetura de Dados Convergente

Nos sistemas e nas aplicações que são criadas hoje em dia, os maiores problemas com Dados em geral são a quantidade de informações geradas, os múltiplos formatos que existem, e a velocidade em que eles se modificam.

Nesse post eu vou comentar um pouco sobre esse tema, e duas maneiras de lidar com isso.


Quando a gente desenvolve um sistema hoje em dia, normalmente nós usamos várias tecnologias que tem a ver com Dados, mas cada uma tem uma finalidade específica, por exemplo:

  • Quando você armazena dados com objetivo de alguém ler depois, você usa um banco de dados;
  • Se você quer lembrar o resultado de uma busca complexa, para acelerar leituras, você usa um mecanismo de cache;
  • Para permitir que os usuários façam buscas por palavras-chave específicas, textos-livres, ou consultas ad-hoc, você usa índices;
  • Para trocar mensagens entre processos, ou entre sistemas, você usa um broker de eventos;
  • E para periodicamente pegar uma grande quantidade de dados acumulados e processar, você faz um processamento batch.

Nós tipicamente pensamos que bancos de dados, caches, filas, são todas ferramentas de diferentes categorias. Por exemplo, um banco de dados e um broker de eventos têm uma certa similaridade, porque ambos armazenam dados por algum tempo. Mas eles são diferentes. Eles têm padrões de acesso diferentes, e características de performance e implementação diferentes.

Além disso, pra cada uma dessas categorias existem dezenas de opções com base em diferentes capacidades. Existem vários tipos de bancos de dados, várias formas e métodos diferentes de fazer cache, e vários tipos de índices para buscar informações. E isso ocorre basicamente porque os sistemas TÊM necessariamente requerimentos diferentes.

E quando a gente desenvolve um sistema, especialmente na camada de persistência, na camada de dados, a gente precisa saber quais ferramentas e quais métodos são os mais apropriados para cada caso, e é difícil combinar ferramentas diferentes quando você precisa fazer uma coisa que uma só ferramenta sozinha não consegue fazer, certo?

A verdade é que no final do dia você, além de você ser um desenvolvedor de software, acaba sendo também um arquiteto de dados.

Então basicamente você tem dois caminhos.

Você tem o caminho onde você vai utilizar várias tecnologias. Você vai aprender todas essas ferramentas. Você vai integrar todas elas. Vai suportar todas elas, e vai garantir que elas funcionem em conjunto.

E você tem um outro caminho. O caminho que eu chamo de “um sistema de dados convergente”. E nesse sistema você tem uma plataforma, e nessa plataforma você tem quase todas as ferramentas, quase todos os tipos de dados…  seja schema on write, seja schema on read, seja um cache, uma fila, não importa o formato dos dados… todos eles, dentro do mesmo sistema de dados. E quando esse sistema não suporta alguma coisa, ele virtualiza o acesso e expõe a mesma interface de acesso pra você consumir aquela informação da forma mais transparente possível.

Veja meu video sobre esse tema:

Teorema CAP

Atualmente existem mais de 300 bancos de dados no mercado, e você precisa escolher aquele que melhor atende sua necessidade.

Os projetistas desses bancos de dados fizeram uma importante decisão sobre como eles devem funcionar, e por isso é importante entender o mecanismo de funcionamento deles para você não errar na escolha.

Entendendo o Teorema CAP você terá uma visão mais clara sobre os tipos de bancos de dados disponíveis, e quais estão aderentes ao seu caso de uso.

Nesse post eu passo uma visão básica sobre o significado do Teorema CAP. Você também pode assistir meu video no YouTube:

Consistency, Availability and Partition Tolerance (CAP)

CAP significa Consistência [do inglês, Consistency], Disponibilidade [do inglês, Availability], e Tolerância a Partição [do inglês, Partition Tolerance].

Partition Tolerance significa que o banco de dados é distribuído em diversos servidores independentes [shared-nothing], em pares de leitura/escrita. Isso é importante, em especial, para aumentar a performance, já que quanto mais você espalha os dados em servidores diferentes, maior é o throughput [megabytes por segundo] de leitura e escrita. Partition Tolerance também significa que se um servidor estiver fora, todo o sistema de banco de dados continua funcionando, com exceção desta parte específica que apresentou a falha.

Você pode perguntar por que P é chamado exatamente de “Tolerância a Partição”. O entendimento de partição aqui é “falha”, e mais especificamente falha de rede, que impede que um servidor se comunique com outro servidor. Então quando um banco de dados tolera partição, significa que se houver falha na comunicação entre um servidor que escreve e sua réplica, o banco de dados não para de funcionar, pois poderá haver outros pares de leitura e escrita no cluster que não estão no caminho da rede que falhou.

Consistency implica em consistência de leitura, e significa que depois que uma informação é escrita, todas as leituras subsequentes vão enxergá-la, no mesmo servidor, ou em suas réplicas. Neste caso também dizemos que há consistência forte, porque todos enxergam a mesma versão da informação.

Availability significa sempre disponível para leitura ou escrita, e todas as requisições sempre retornam alguma informação, mesmo que ela esteja inconsistente – mas nunca retorna um erro. Isto é, pode ter havido alguma falha na rede e os pares de servidores leitura/escrita não se enxergam, mas ambos permanecem abertos e recebem operações, estando em estado eventualmente consistente. Por causa disso, também dizemos que há uma consistência eventual, porque não é certeza que todos enxergam a mesma versão da informação.

A Prova

O Teorema CAP foi provado, e ele diz que das três propriedades desejadas, apenas duas podem existir ao mesmo tempo para um par leitura/escrita.

Isso nos leva a três possibilidades que definem o mecanismo de funcionamento de um banco de dados.

CA – Consistency e Availability: são bancos de dados cujos dados não estão distribuídos, mas oferecem consistência, e também disponibilidade [porém, em geral através de failover, isto é, com downtime]. O Oracle RAC é o único atualmente que oferece tanto C como A “sem downtime” em um sistema de banco de dados que não tolera partição [shared-disk].

CP – Consistency e Partition Tolerance: são bancos de dados que oferecem consistência, isto é, os pares leitura/escrita sempre estão com os mesmo dados [consistentes], mas caso haja alguma falha na rede, ambos tornam-se indisponíveis: sacrificam a disponibilidade em favor da consistência.

AP – Availability e Partition Tolerance: são bancos de dados que oferecem disponibilidade, e sacrificam a consistência. Isto é, os pares leitura/escrita permanecem operantes quando há falha na rede. Notadamente, quando isto ocorre eles ficam em estado inconsistente, pois não há uma comunicação entre eles. A inconsistência pode ser resolvida quando a comunicação é reestabelecida.

Minha Opinião… e a Sua?

Primeiramente, a letra A do CAP implica em uma premissa que eu particularmente não concordo.

A significa sempre disponível para leitura e escrita, mas sabemos que disponibilidade é medida em 9s depois da vírgula, e nada é realmente 100%. Quanto mais rotas redundantes de rede, e mais réplicas dos dados, mais 9s de disponibilidade teremos depois da vírgula, mas nunca 100% como o teorema preconiza.

Um outro ponto é que potencialmente, salvo implementação específica de cada banco de dados, os sistemas AP sempre apresentam um estado de consistência eventual, mesmo sem falha/partição na rede. Isso ocorre porque a propagação dos dados entre o servidor de que escreve e o servidor de réplica é assíncrona. Desta forma uma leitura pode ocorrer antes que uma informação que acabara de ser escrita fosse transmitida pela rede até o servidor em questão. Considerando que atualmente falhas de rede são raras, e as redes de comunicação locais são rápidas, sistemas AP oferecem uma desvantagem permanente, e na minha visão, desnecessária, tornando-os nicho para necessidades muito específicas. Há uma tendência de mercado dos bancos de dados NoSQL migrarem para o paradigma CP.

Então antes de usar um banco de dados, em especial nesses tempos de micro-serviços e persistência poliglota, atente-se ao mecanismo que é implementado no banco de dados.

Requisitos de elasticidade e alto throughput para leitura e escrita exigem que o banco de dados seja tolerante a partições. E neste caso, se houver a necessidade de consistência forte, o banco de dados deverá ser CP, do contrário, escolha AP.

Document Stores sempre serão um Nicho?

Document Stores são uma espécie de subcelebridade dos bancos de dados. Eles apareceram de repente, têm supostamente alguma relevância, mas todos os outros bancos de dados Não-Document Store já fazem o que eles fazem: Oracle, MySQL, SQL Server, PostgreSQL, DB2, ElasticSearch, Redis, MariaDB…

Document
Stores
Não-Document Stores
(Multimodel DBs)
Suporte a DocumentosXX

Eles são amados principalmente por front-end devs, porque Documentos permitem a mais rápida prototipação. É inegável.

O grau de flexibilidade de schema é tão alto que causa piripaques nos administradores de dados mais tradicionais. Alguns até proíbem.

Mas só depois que você usa o Modelo de Documentos você percebe o quão rígido é o Modelo Relacional. É incrível como um é o oposto do outro. Há de verdade um perigo real e iminente de você se lambuzar e querer colocar Document Stores em todos os lugares.

Bom, devo lembrar que este artigo não é exatamente sobre Documentos JSON ou XML – é sobre Document Stores: bancos de dados que só armazenam Documentos. Não confunda.

Fiz um video em meu canal no YouTube, com conteúdo para database developers, explicando algumas diferenças de arquitetura entre esses dois modelos:

Variedade, Velocidade e Volume.

Document stores resolvem principalmente a Variedade nos 3 Vs que definem Big Data, porque eles são schema-less, e por isso suportam uma grande variedade de formatos de dados.

Essa variedade é também o que lhes impede de serem completamente aderentes ao ACID, porque a letra C significa Consistência de Escrita [Schema], e Document Stores são, por definição, sem schema. Mas isso não lhes impede de suportar transações [Atomicidade, Isolamento e Durabilidade].

Há os que consideram 5 Vs, tendo Veracidade e Valor como os dois Vs adicionais. Neste post vou considerar apenas aspectos técnicos, por isso são 3 Vs.

A Velocidade nesse tipo de persistência é entregue através de particionamento dos dados: os documentos são distribuídos em partes [servidores] diferentes pela chave que identifica um documento.

Atualmente apenas tecnologias que escalam horizontalmente, como as que particionam os dados, conseguem suportar os mais altos volumes de leitura e escrita. Ainda não existe um teorema que prove isso, mas meu feeling diz que nunca vai existir outra arquitetura que escale mais, pelo menos até a popularização da computação quântica.

É questionável um Document Store ter grande desempenho quando não se pesquisa pela chave, mesmo que o banco de dados suporte índices secundários.

Pesquisas por chave são resolvidas com Hash, e índices secundários em geral são resolvidos com Árvores Binárias. Em uma análise assintótica, Hash é O(1), e Árvore Binária é O(Log n), e O(Log n) é mais lento que O(1). E uma busca por um índice secundário particionado é na melhor das hipóteses O(Log N) + O(1).

A maioria dos bancos de dados Não-Document Store que citei no início, que suporta Documentos, também suporta particionamento de dados.

Document
Stores
Não-Document Stores
(Multimodel DBs)
Suporte a DocumentosXX
Suporte a ParticionamentoXX

E como Document Stores se diferenciam em relação ao Volume?

Qual é o tipo de persistência que você acredita que tem maiores dificuldades com grandes volumes? Relacional? Bom, já pensou que um banco relacional é normalizado justamente para reduzir grandes volumes?

Vou explicar “normalizar” explicando “desnormalizar“.

Desnormalizar tem um significado que é agregar dados, um benefício que é agregar dados, e um problema que é agregar dados.

Document Stores são do tipo do segundo ‘agregar dados’, o do benefício. Para eles, desnormalizar significa aumentar o desempenho das consultas no banco de dados, porque a final de contas, dados agregados evitam joins, e joins são lentos, segundo eles.

Bancos Relacionais são do tipo do terceiro ‘agregar dados’, o do problema. Para eles, desnormalizar significa aumentar problemas de integridade nas escritas no banco de dados, pois como os dados não-chave não dependeriam funcionalmente só da chave [terceira forma normal], poderia haver valores duplicados e inconsistentes.

Pense que um banco de dados relacional com o tamanho de 10 TBytes em 3NF, se desnormalizado, atingiria fácil os 100 TBytes.

Isso ocorre porque esses bancos relacionais normalizam os dados, e eles fazem isso substituindo as repetições por um código [chaves estrangeiras]. A maneira mais vulgar de explicar isso é dizer que eles ‘desduplicam’ os dados.

Desduplicar na área de algoritmos de compressão significa substituir um valor que se repete por um símbolo de tamanho pequeno [um tipo de compressão sem comprimir]. Então como os bancos relacionais fazem isso como parte da sua natureza, posso dizer que um banco de dados relacional é um Big Data desduplicado.

Pare por um momento e pense. É isso mesmo. Um banco relacional suporta volumes colossais e você não sacou. Eles só estão desduplicados!

E o que isso tem a ver com os Document Stores? Basicamente isso indica que ambos têm a mesma capacidade de armazenar grandes volumes, porém o fazem de forma diferente. Isso também indica que qualquer coisa, menos o Excel (risos), consegue armazenar grandes volumes de dados.

Document
Stores
Não-Document Stores
(Multimodel DBs)
Suporte a Documentos
(Variedade)
XX
Suporte a Particionamento
(Velocidade)
XX
Suporte a Grandes Volumes
(Volume)
XX

Um desnormaliza para ter performance de consulta, e o outro normaliza para ter integridade. E o benefício de um, é o trade-off do outro.

O fato dos Não-Document Stores que citei no início deste post também suportarem Documentos, indica que eles são híbridos no sentido de que o desenvolvedor poderá escolher em qual parte do trade-off ele vai querer estar, em partes independentes do código, e em partes diferentes das informações que estiver armazenando.

Em outras palavras, ele poderá escolher qualquer combinação do C do ACID [consistência de escrita], com o C do CAP [consistência de leitura], particionado ou não.

Document
Stores
Não-Document Stores
(Multimodel DBs)
Suporte a Documentos
(Variedade)
XX
Suporte a Particionamento
(Velocidade)
XX
Suporte a Grandes Volumes
(Volume)
XX
undefinedX

Status Quo

O grande problema dos Document Stores para serem os Panteões de Todas as Persistências e de Tudo o Mais é o fato de eles serem schema-less.

O benefício da Variedade afetou sua relevância.

A história mostra que antes e após o Modelo Relacional, as formas de persistência de dados têm sido schema-less, onde só a aplicação entende como os dados estão organizados. Todas elas falharam como status quo, sumiram, ou são apenas nichos tornando-se subcelebridades [importantes pontualmente].

Qualquer modelo de dados onde você tem que conhecer a aplicação para entender os dados vai falhar no caminho para o mainstream, e será sempre um nicho.

Winter is Coming: Como Sobreviver em um Mundo com Persistência Poliglota?

Eu costumo dizer que bancos de dados são como queijos e vinhos, pois eles melhoram enquanto envelhecem.


No início existia apenas uma arquitetura de dados one-size-fits-all: a solução para todo e qualquer problema.

O que vemos hoje é uma verdadeira miscelânea, centenas de combinações e permutações possíveis de formatos diferentes, tecnologias, e integrações de todas as latências. Você já não sabe se tem que ser streaming ou batch, síncrono ou assíncrono, schema-less ou schema-full, SQL ou NoSQL, se a consistência mais adequada é eventual ou forte, o relacionamento é entre nós de um grafo ou entre chaves de tabelas, se precisa ser scale-up ou scale-out, e se é necessário um Data Lake ou um Data Warehouse.

Se identificou? Continue lendo.

Este artigo é sobre uma das maiores tendências a respeito de como organizar toda essa bagunça: persistência poliglota multi-modelo. Esta coisa de nome complicado, longo, e difícil de falar [eu entendo], é a fusão de uma dezena de tecnologias já testadas em batalha, e que provavelmente será, eu estimo, o futuro da arquitetura de dados. Será como antes só que o oposto: de one-size-fits-all, para all-fits-one-size.

O Início de Tudo: a Jornada do Herói

Nos primeiros sistemas de banco de dados, se é que podemos chamá-los de “sistemas” diante da primitividade que pairava no início, eu me lembro de ter lido que para conseguir uma informação você tinha que [1] saber qual era o arquivo onde ela estava, e [2] qual era o registro nesse arquivo, e [3] então quais eram as suas posições de início e término no registro. Essas posições eram sempre fixas, a propósito. Nessa estrutura, que se chamava ISAM, basicamente, você tinha que ter um mapa que lhe explicava como os dados que eram gravados, para poder buscá-los depois.

Não vou detalhar com mais profundidade sobre a estrutura de dados ISAM, pois assim como eu, hoje, você não vai querer saber!

Um senhor chamado Edgar Codd, pesquisador da IBM [claro, todos os pesquisadores da época eram da IBM] disse que as pessoas não deveriam ter que se preocupar em como os dados estavam organizados para entendê-los. Isso se tornaria um caos num futuro reservado para os Megabytes [hoje, Terabytes].

Codd então criou o Modelo de Dados Relacional. Era um mecanismo engenhoso, porém simples, que desacoplava os dados da organização física deles. Uma simples frase como “selecione os dados do cliente, na tabela de clientes” foi capaz de substituir milhares de linhas de código, e acelerar em ordens de magnitude o tempo para buscar as informações.

Eis que surge Larry Ellison, com mais alguns amigos. Enquanto uns apenas viam o que seus olhos enxergavam, Larry enxergava o que seus olhos viam: nada inventado antes era mais completo e eficiente do que o Modelo de Dados Relacional. Naqueles anos 70, era o futuro. E foi mesmo. E esse futuro ainda não acabou.

Surgiu o Oracle Database como o primeiro sistema gerenciador de banco de dados baseado no Modelo de Dados Relacional. Uma locomotiva de inovação a toda velocidade passou entre os anos 80, 90 e 2000. Foi incrível a quantidade de recursos criados, e até hoje alguns desses recursos ainda são exclusivos.

Muitas outras tecnologias surgiram: ora morriam pelo caminho, ora apenas sobreviviam com uma vida de ócio e defasagem diante da constante evolução do Oracle.

CAP, e os 300

O ano 2000 entra, a internet começa, e o suposto declínio do Modelo Relacional é ensaiado. A internet é um colosso perto dos sistemas empresariais. Por um minuto você tem 10 usuários, e no momento seguinte, instantaneamente, você tem 1 milhão. Projetado para funcionar em servidores que escalam verticalmente, os Bancos de Dados Relacionais realmente não funcionam nesse novo paradigma.

Eric Brewer formula uma conjectura que alguns anos mais tarde se tornara um teorema, o teorema CAP. Esse teorema basicamente forma a base para a criação de estruturas de dados que seriam mais adequados para a internet do que o Banco de Dados Relacional. Em essência, são estruturas de dados que escalam horizontalmente.

O teorema CAP é realmente uma ideia estranha, mas foi provada matematicamente. A letra A do CAP significa “sempre disponível para leitura e escrita“, o que implica em uma disponibilidade de 100%. Ora, nada nesse mundo tem 100% de disponibilidade. Nem o mundo tem 100% de disponibilidade. Bom, essa é uma premissa que não concordo, mas em função dela o CAP é um teorema, e com teoremas não se discute.

A ideia colou, mais de 300 bancos de dados Não-Relacionais foram criados, e a internet explode. Todo hype é então construído baseado em estruturas Não-Relacionais.

Dá-se então início a vários formatos de dados diferentes.

Timidamente, primeiro foram as estruturas Objeto-Relacionais. Essas morreram rápido. Prometeram de mais, fizeram de menos. Cometeram o mesmo pecado do ISAM: era necessário compreender os Objetos para entender os dados. Retrocesso. Curiosamente, os Bancos Relacionais absorveram o modelo lógico Objeto-Relacional, junto do Relacional, para quem quisesse usar, inclusive, no mesmo comando SQL.

É o início dos Bancos de Dados Multi-Modelo. Relacional com Objeto.

Depois surgiram as estruturas de armazenamento XML. Menos complexas do que os Objeto-Relacionais, pois elas tinham schema, e XPath para percorrer os dados. XML ficou bons anos em evidência. Mas também falhou. E novamente, os bancos relacionais absorveram o modelo lógico XML, junto do Relacional, para quem quisesse usar, no mesmo comando SQL.

Relacional, Objeto e Documento XML.

Em paralelo surgiu a necessidade de bancos de dados com capacidades de geo-processamento, os Bancos de Dados Espaciais. Nenhum fez sucesso como um produto a parte, porém, essa camada de persistência se juntou aos Relacionais, como uma outra camada lógica, e ainda é usada hoje, desta forma, como parte dos bancos relacionais.

Relacional, Objeto, Documento XML e Geo-Espacial.

Mais próximo dos tempos atuais, despontou como uma forma de armazenamento bastante comum o formato JSON, com grande flexibilidade e agilidade: os desenvolvedores adoram. No entanto, apesar de alguns bancos de dados puramente baseados nesse formato terem se tornado relevantes, os bancos de dados relacionais que outrora haviam absorvido vários outros modelos lógicos, também absorveram o formato JSON.

A partir de agora é muito mais fácil um Banco de Dados Multi-Modelo acrescentar uma nova estrutura lógica, do que um banco de dados especializado implementar as capacidades mais básicas, como Consistência Forte, ou mesmo SQL, por exemplo.

Relacional, Objeto, Documento XML e JSON, e Geo-Espacial.

Outras estruturas de dados com usos mais específicos também fizeram parte do big bang causado pelo teorema CAP: Grafos, Chave/Valor, Colunares e Motores de Busca. Adivinha? Os bancos de dados relacionais adicionaram mais camadas lógicas para suportar essas estruturas.

Destaco que de todos esses, o Modelo de Grafos é o mais diferente. É o mais engenhoso. E provavelmente é o que eu gosto mais. É também assunto para outro artigo.

Enquanto que do ponto de vista de estrutura de dados os Bancos Relacionais fizeram grandes intervenções para suportar tudo o que o mercado demandava, por outro lado, num passe metamorfósico, esses bancos também passaram a escalar horizontalmente, para os lados e não somente para cima, como todos os outros 300 bancos de dados Não-Relacionais já faziam. Dá-se o nome de NewSQL, uma alusão aos bancos Não-Relacionais [NoSQL] com a consistência forte dos Relacionais e o suporte completo ao SQL [basicamente, SQL é um sonho de toda a vida de um NoSQL, Apache Hive que o diga].

Esses super Bancos de Dados Relacionais, que suportam vários modelos de dados, e escalam tanto para cima como para os lados, são chamados finalmente de Bancos de Dados Poliglotas Multi-Modelo. Eles possuem toda a herança de inovação dos fundamentos essenciais para gestão de dados, o suporte aos principais formatos de dados dos últimos 40 anos, e a capacidade de escala que é um dos requerimentos para aplicações modernas de internet e Big Data.

Um outro fator relevante se soma a esses super bancos de dados: cloud automation. Poucos cliques ou chamadas de API permitem que toda essa estrutura seja criada, e mantida automaticamente.

De Codd ao Uber

As arquiteturas de dados são como um trem em alta velocidade, com curvas e hypes pelo caminho. Sempre surgem aquelas tecnologias que só elas fazem aquilo, que são mais típicas de “aplicações de ponta”, mas depois elas acabam convergindo para o mainstream porque as aplicações de ponta hoje são as aplicações mainstream de amanhã.

É por isso que tenho uma preferência particular por Bancos de Dados Multi-Modelo. Você absorve todas as inovações que surgem ao longo dos anos, e herda todas as capacidades fundamentais que as aplicações de ponta ainda não têm.

Meu Uber chegou! A propósito, ele me localizou com geo-processamento, o pagamento da minha corrida vai persistir com a integridade de um modelo relacional, e todas as outras coisas devem estar agregadas em documentos JSON em uma estrutura scale-out, pois afinal é mobile e precisa ser escalável.

Como poderia dizer Codd: as pessoas não deveriam ter que se preocupar em como os dados estão organizados para entendê-los. Isso pode se tornar um caos num futuro reservado para os Pegabytes…

Com Reduzir em 100% seus Problemas com Armazenamento de Dados (não é propaganda)

Cientistas descobrem uma forma de armazenar dados que levam os desenvolvedores à loucura!


Os recursos mais interessantes dos provedores de Cloud no mercado, sem dúvida, são todos os tipos de Cloud Storage que você pode escolher e provisionar com alguns cliques. Neste post vou falar sobre o principal deles: Object Storage.

Francamente, o nome “Object Storage” não é amigável, e tampouco inspira algo moderno. Esse nome é nauseante, nauseabundo, nauseoso, ascoso, e todos os outros 28 sinônimos de repugnante. Se você ainda não conhece Object Storage, certamente é por causa do nome dele. Soa técnico demais, e excessivamente “coisa de infra”. Mas acredite, é “coisa de developer“.

Os nomes dos seus pares também não são dos melhores: diretórios e sistemas de arquivos [filesystems]. Esses nomes me lembram aquelas gavetas do meu escritório que abro uma vez a cada década. A verdade é que os nomes das coisas que referem-se às formas de persistência sempre me lembram armários, gavetas, pastas, baldes e caixas.

… de volta à dissertativa: há muitos anos, ou melhor, em todos os anos desde o início da era dos bancos de dados relacionais, quase TODAS as informações têm sido armazenadas em diretórios e sistemas de arquivos. Mas os anos passam, e alguém sempre inventa algo melhor. Continue lendo.

A Vida antes do Big Data

Antes de entrar no fantástico mundo do Object Storage, que apesar do nome, é realmente fantástico, tenho que desconstruir os filesystems. Rebaixá-los. É! Este post é propositalmente enviesado para enaltecer o poder do Object Storage em detrimento de outras formas de persistência mais convencionais. Desista aqui se não concorda.

Filesystems são ruins. Muito ruins. Eles são fixos. Têm limites. São cheios de regras. Não entendem HTTP, e pior: eles se falam por SAN e NAS [high-tech da época que seu pai ouvia Roupa Nova].

Filesystems são carentes de software inteligente e precisam de alguém para tomar conta – e fazer coisas totalmente zero business value: criar LUNs, formatar e montar discos, e configurar RAID.

Filesystems tornam-se naturalmente lentos enquanto crescem. Tento não acreditar que “ficar lento” faz parte da arquitetura deles, mas a verdade é que com o tempo eles ficam lentos por definição. Esse é o principal motivo pelo qual eles não suportam a escala da internet.

Explicando escala da internet: pense em uma Vespa. Sim, o inseto. Ela está parada, e de repente vai a 100 km/h, e para [freia no ar]. Depois ela faz uma curva de 90 graus, e acelera instantaneamente até 100 km/h de novo. De zero a 100 km/h em 0,00001 segundo. Agora ela faz outra curva de 90 graus sem parar, ignorando as forças da gravidade e da inércia. Agora troque a “Vespa” por “quantidade de usuários que acessam o seu sistema“. Pronto! Você já tem uma ideia do que é a escala da internet!

Obrigado Filesystems! Obrigado por nos ajudar no mundo dos megabytes e das coisas pequenas. Não nos veremos mais, pois agora as coisas são grandes demais pra vocês.

O Novo Centro do Universo

Há também aqueles que dizem que os bancos de dados também não suportam a escala da internet. Nenhum deles. Nécas. Nadicas. E isso inclui a maioria dos NoSQL. Sim, nem eles escapam.

O principal argumento é: dados não-estruturados [fotos, vídeos e textos] são complexos demais para os banco de dados. Se eu concordo? Em relação aos filesystems, sim, claro. Eles realmente não escalam. Mas e os bancos de dados? Prossiga na leitura.

Passaram por cima de todas as formas de persistência que existia, e criaram uma coisa que mais parece a pia da minha cozinha depois daquele almoço de domingo, e eles chamam de Object Storage. Agora esse treco é o centro do universo. Você coloca tudo lá, e ele se resolve [o Object Storage, não a pia da minha cozinha!].

Bom, mas e os bancos de dados?

O que diz minha chatbot Alexandra?

Fernando: Alexandra, o que você usava para armazenar os dados das suas aplicações web?
Alexandra: filesystems e bancos de dados.
Fernando: e o que você usa agora?
Alexandra: Object Storage.
Fernando: mas e o ACID, o 2-Phase Commit, a consistência forte, o teorema CAP que levei uma vida pra entender?
Alexandra: Não precisa.
Fernando: Precisamos ter uma conversa franca sobre coisas limitadas, a pia da minha cozinha, e a volta daqueles que não foram.

Uma Conversa Franca sobre Coisas Limitadas

Há dois tipos de filesystems: os tradicionais, e os que ainda não perderam as esperanças, mas todo mundo já sabe que eles já não têm mais futuro.

Os Filesystems Tradicionais

O primeiro são os filesystems tradicionais, baseados em SAN e NAS, que você provavelmente tem no seu data center on premise. Eles falham feio quando precisam escalar no nível da internet [Petabytes] – e se você acha que Petabyte é muito e nunca vai lhe atingir, lembre-se que há 20 anos um gigabyte era mais inimaginável do que você receber uma cesta de Lindt diretamente das mãos do Coelhinho da Páscoa, fora da Páscoa, no meio de deserto do Saara.

Filesystems precisam de uma tabela de lookup para localizar os arquivos. E essa tabela cresce. Imagine um banco de dados sem particionamento, compressão, paralelismo, índices… é isso. A tabela de lookup dos filesystems me lembra, carinhosamente, o DBU do Clipper.

Essas tabelas de lookup crescem até ao ponto que nada mais funciona. E então neste momento os administradores de storage fazem algo incrível:

Eles criam outra LUN.

Pense na LUN como a cauda de uma lagartixa. As lagartixas soltam sua cauda para confundir o predador e facilitar a fuga. Depois a cauda se regenera.

Quase a mesma coisa acontece com as LUNs. Quando a tabela de lookup fica grande, cria-se outra LUN para confundir o sistema operacional, deixando tudo mais rápido, mas depois a LUN cresce novamente e o processo se repete.

O grande problema é que as LUNs não fogem. Elas ficam lá para sempre e você tem que administrar! E quando você tem muitas LUNs e precisa dar um reboot no servidor, começa a ficar mais claro a definição de “anos-luz” que os cosmonautas usam para medir o tempo que leva para percorrer as viagens no espaço.

Por causa disso os filesystems tradicionais são os grandes perdedores na era do Big Data. Eles simplesmente não existem nesse mundo.

Os Filesystems Scale-Out

Hadoop Distributed Filesystem, HDFS, esse é o nome dele.

HDFS é independente de hardware. Os arquivos, cujos tamanhos não têm limite, são armazenados em blocos que se espalham entre vários discos do mesmo servidor, e entre discos de vários servidores. É scale-out afinal, isso já diz tudo: escala para os lados.

Ele parece melhor que os filesystems tradicionais, certo? Certo! Continue lendo.

HDFS resolve o problema de escalabilidade, mas … você precisa de um high-skilled high-salary high-high-high engenheiro de dados para mantê-lo no ar.

E complementado o “para mantê-lo no ar”: HDFS faz parte de um ecossistema que mais parece um zoológico composto por Zookeeper, Pig, Hive, Flume, HBase, YARN, Ambari … e o que mais mesmo ?! Divirta-se!

HDFS é muito labor-intensive. Sem falar na tripla redundância padrão que faz você gastar 3 PBytes para cada 1 PByte de dado útil. E você ainda acredita que esses filesystems são low cost porque, afinal de contas, o hardware é commodity, certo?

Risos.

HDFS é um filesystem em larga escala. Filesystem é um problema. Logo, HDFS é um problema em larga escala. HDFS é o máximo que se pode obter em larga escala de um filesystem no mundo on premise.

A nuvem chegou, e a festa vai começar. Não pare de ler.

A Pia da Minha Cozinha depois do Almoço

Nesta parte do texto meu objetivo é explicar para você, com um nível bastante aprofundado de detalhes, o que é Object Storage, e quais são seus benefícios.

Se você acha que um nível aprofundado de detalhes é como 100 páginas, esqueça!

Vou gastar um esforço colossal para tentar colocar 20 palavras numa frase. Não há muito segredo. Object Storage é simples por mais que eu tente criar alguma complexidade. Ele é flat, não tem diretórios ou hierarquias. Você coloca o arquivo lá, e ele vai. Você pede o arquivo, e ele vem.

Object Storage, um dos tipos de Cloud Storage, armazena porções de dados que podem ser identificadas individualmente. Essas porções podem ter metadados associados, e são acessados por meio de APIs. Os provedores de Cloud fazem a gestão do Object Storage, não você.

Arquivos nos filesystems são “objetos” no Object Storage.

O Object Storage também é composto por discos, como os filesystems, mas a diferença é que há “serviços” que fazem o gerenciamento dos arquivos, ao invés de deixar que essa gestão seja feita no nível do sistema operacional.

Esses serviços apresentam os discos como se fossem uma coisa só, formando uma camada de abstração maior, um pool. Cada arquivo que você coloca lá tem um ID, e é tudo que você precisa saber.

O Object Storage expõe seus objetos [arquivos] através de uma interface REST. Então você pode colocar ou recuperar arquivos usando o protocolo HTTP.

No exemplo abaixo eu faço três operações. Vou usar o curl [que é uma espécie de browser em formato texto] para executar operações HTTP:

curl -X PUT -H "X-Auth-Token: codigo_token" https://url/piaCozinha

curl -X PUT -H "X-Auth-Token: codigo_token" https://url/piaCozinha -T meuArquivo.txt

curl -X GET -H "X-Auth-Token: codigo_token" https://url/piaCozinha

Em todas as chamadas precisamos passar um token para segurança, que é gerado antes. E depois usamos comandos HTTP, como PUT, POST, DELETE e GET sobre uma URL [endpoint], que é fornecido pelo seu provedor de cloud para operar sobre um Object Storage.

Na linha 1 eu criei um container chamado piaCozinha, que é onde vão ficar meus arquivos [é como se fosse um diretório].

Na linha 3 eu coloquei um arquivo chamado meuArquivo.txt no container piaCozinha.

Na linha 5 eu busquei todos os arquivos no container piaCozinha, através da operação HTTP GET.

Simples, certo? Acredite, não tem mais nada.

Qual é o lado ruim e perverso desse tipo de persistência?  Imutabilidade [não pode alterar], e segue o AP do teorema CAP [disponibilidade e particionamento, e não consistência].

Como o caso de uso principal do Object Storage é armazenar dados não-transacionais, então esse lado perverso é menos perverso do que parece.

No final do dia, por causa das APIs, Object Storage significa que os desenvolvedores não precisam da benção do pessoal de infraestrutura para alocar mais espaço para a aplicação.

Está ficando quente. Continue lendo.

A Volta Daqueles que Não Foram

É inegável que SQL é a forma mais human-friendly para buscar qualquer coisa. Apache Hive sabe disso. Então melhor do que armazenar arquivos em Object Storage, é processá-los utilizando SQL.

Quais são os melhores engines de SQL? Os bancos de dados. 

Agora vai começar a era onde os bancos de dados processam os dados que armazenam, e também os dados que não armazenam.

Os bancos de dados se tornarão sistemas gerenciadores de dados, não importa onde os dados estejam.  E não estou falando de BLOBs. Estou falando de Object Storage, e em qualquer formato: Parquet, Avro, CSV ou whatever.

Eu tenho uma visão que o padrão do mercado será armazenar boa parte dos dados, não importa o formato, em Object Storage, e esses dados serão acessados nativamente com SQL por sistemas gerenciadores de dados.

Obrigado ecossistema Hadoop/HDFS! Obrigado por aumentarem um pouco a escala das coisas no mundo On Premise, mas no mundo Cloud é a vez dos Object Storages.