Quando nós, desenvolvedores, ouvimos o termo proliferação de dados (data sprawl), pode soar um pouco como um termo de negócios, como TCO, ROI e afins. Todos esses termos têm uma realidade para os desenvolvedores, fora do reino de analistas e gerentes. Então, hoje quero falar sobre a realidade da proliferação de dados para os desenvolvedores. Como isso impacta nosso trabalho.
Data Sprawl can be summed up as we have data, a tremendous amount, stored in many different data stores. And on top of that, we as developers have to make those datastores interact with each other. And of course the more, the merrier, right 😬?
Normalmente, isso está associado a custos financeiros mais elevados em:
- Infraestrutura
- Licenças
- Integração
- Treinamento
- Operacional
- Custos de suporte
Plataformas separadas com múltiplas interfaces vão lhe dar dor de cabeça por causa de:
- Implantação e gerenciamento independentes
- Diferentes modelos de dados e interfaces de programação
- Integração entre múltiplos produtos
- Chamados de suporte com diferentes fornecedores
E precisamos dedicar mais tempo, esforços e recursos financeiros devido a:
- Licença e contrato
- Treinamento para Desenvolvedores e Operações
- Apoio
- Criar API ou conector para banco de dados
- Infraestrutura de compras
É um pouco sombrio quando você olha para isso assim, mas é um desafio diário para muitas empresas. E não apenas com diferentes cargas de trabalho de dados, isso também é verdade para os aplicativos em nuvem.
Vamos dar uma olhada em um exemplo específico. Eu criei um aplicativo que usa CRUD a partir de um banco de dados de documentos, Cache a partir de um armazenamento de cache e busca a partir de um mecanismo de busca de texto completo. (Código-fonte do GitHub)
Analisando este esquema, você basicamente pode contar cada seta que vê como uma interação entre diferentes sistemas sobre a qual os desenvolvedores têm que pensar e codificar.
Aqui estamos sincronizando automaticamente os bancos de dados de Cache e de Busca usando *event streaming*. Isso representa 8 interações e 4 armazenamentos de dados para aprender e gerenciar. Como você precisa garantir que cada armazenamento esteja conectado ao serviço de *streaming* e receba as atualizações corretas, você precisa gerenciar o serviço de *streaming*, a busca, o cache e o armazenamento de dados. Você também precisa integrar o cache com o seu serviço de CRUD (idealmente com os outros serviços, mas vamos manter isso simples). Em suma: há muito o que fazer.
Podemos limitar essas interações nos livrando dos serviços de streaming e garantindo que outros serviços sejam atualizados manualmente. Esta é uma licença a menos, coisa para operar, coisa para aprender, coisa para integrar. Ainda não é o ideal, mas poderia ser assim:
É um pouco mais simples, apenas 6 interações e 3 armazenamentos de dados em vez de 8 e 4. Mas ainda há muitas interações e parte da integração de streaming precisa ser feita manualmente. Enquanto isso, antes poderíamos ter aprendido e usado conectores existentes entre serviços existentes. Vamos dar uma rápida olhada no código de exemplo em Java/Spring Boot escrito para isso.
Existem 4 interfaces que representam o que os desenvolvedores podem fazer com bancos de dados: CRUD, Cache, Query e Search.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
público interface CRUD { StoredFileDocument read(String identidade); vazio criar(String identidade, StoredFileDocument doc); vazio atualizar(String identidade, StoredFileDocument doc); vazio atualização upsert(String identidade, StoredFileDocument doc); vazio delete(String identidade); } público interface Cache { vazio writeInCache(StoredFileDocument doc); StoredFileDocument readFromCache(String identidade); vazio touch(String identidade); vazio evict(String identidade); } público interface Query { List<Map<String, Object>> consulta(String whereClause); List<Map<String, Object>> findAll(); } público interface Pesquisar { List<Map<String, Object>> pesquisar(String term); vazio index(StoredFileDocument doc); vazio delete(String identidade); } |
Não vamos mostrar todo o código nesta postagem, mas apenas alguns dos trechos mais interessantes.
Estamos em uma configuração onde o serviço CRUD possui links para os serviços de Busca e Cache. Vamos ver como ficaria com uma versão simplificada. Precisamos importar os serviços de Cache e Search, pois eles são obrigatórios. A partir daí, cada método é impactado por isso. A leitura precisa primeiro consultar o cache, atualizar a última vez que o objeto foi encontrado no cache ou obtê-lo do banco de dados e inseri-lo no cache. Em seguida, os métodos Criar, Atualizar e Excluir afetam o Cache e a Busca, pois os dados recém-criados, atualizados ou excluídos precisam ser propagados para o Cache ou para os índices do armazenamento de dados de Busca.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
@Service público class MongoCRUD implements CRUD { private MongoCollection<StoredFileDocument> coleção; private Cache cache; private Pesquisar pesquisar; público MongoCRUD(MongoCollection<StoredFileDocument> coleção, Cache cache, Pesquisar pesquisar) { this.coleção = coleção; this.cache = cache; this.pesquisar = pesquisar; } @Override público StoredFileDocument read(String identidade) { StoredFileDocument doc = cache.readFromCache(identidade); if (doc == null) { Sistema.fora.println(identidade); doc = coleção.find(eq(“fileId”, identidade)).first(); cache.writeInCache(doc); } else { cache.touch(identidade); } retornar doc; } @Override público vazio criar(String identidade, StoredFileDocument doc) { doc.setFileId(identidade); coleção.insertOne(doc); cache.writeInCache(doc); pesquisar.index(doc); } @Override público vazio atualizar(String identidade, StoredFileDocument doc) { coleção.findOneAndReplace(eq(“fileId”, identidade), doc); cache.touch(identidade); pesquisar.index(doc); } @Override público vazio atualização upsert(String identidade, StoredFileDocument doc) { FindOneAndReplaceOptions Opções = novo FindOneAndReplaceOptions().atualização upsert(verdadeiro); coleção.findOneAndReplace(eq(“fileId”, identidade), doc, Opções); cache.touch(identidade); pesquisar.index(doc); } @Override público vazio delete(String identidade) { coleção.deleteOne(eq(“fileId”, identidade)); cache.evict(identidade); pesquisar.delete(identidade); } } |
Com o Couchbase, isso seria mais próximo de algo assim:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
@Service @Profile(“couchbase”) público class CouchbaseCRUD implements CRUD { private Collection coleção; público CouchbaseCRUD(Collection coleção) { this.coleção = coleção; } @Override público StoredFileDocument read(String identidade) { GetResult res = coleção.obter(identidade); retornar res.contentAs(StoredFileDocument.class); } @Override público vazio criar(String identidade, StoredFileDocument doc) { MutationResult res = coleção.inserir(identidade, doc); } @Override público vazio atualizar(String identidade, StoredFileDocument doc) { MutationResult res = coleção.substituir(identidade, doc); } @Override público vazio atualização upsert(String identidade, StoredFileDocument doc) { MutationResult res = coleção.atualização upsert(identidade, doc); } @Override público vazio delete(String identidade) { MutationResult res = coleção.remove(identidade); } } |
O motivo de não precisarmos de uma dependência para o serviço de Cache e Busca é que o Couchbase já integra um cache e um mecanismo de busca. Não há necessidade de implementar a interface Cache, nem de implementar os métodos de exclusão e indexação da interface de busca. É tudo automatizado e integrado.
Geralmente, quando explico isso para alguém, segue-se uma conversa sobre o quão ruim deve ser, porque você tem que fazer concessões para conseguir fazer todas as coisas. Todas as Plataformas de Dados, multi-modelo, multi-carga de trabalho, não importa como você queira falar sobre elas, não são criadas iguais, ou pelo menos não com a mesma arquitetura em mente.
O Couchbase pode ser visto como vários bancos de dados diferentes, todos responsáveis por cargas de trabalho distintas e integrados por meio de seu serviço de streaming interno. Dessa forma, cada parte do Couchbase é mantida atualizada automaticamente e cada parte pode se spezializar em sua própria carga de trabalho de dados. No fim, você obtém 3 interações e 1 armazenamento de dados.
Agora, isso já é bem legal, mas nós temos mais uma coisa. Nossos serviços são integrados à nossa linguagem de consulta SQL++. Vejamos um exemplo. Você tem um CMS que contém uma árvore de documentos, com várias permissões em cada documento, e essas permissões podem ser herdadas por documentos filhos nos quais você deseja executar uma pesquisa como um usuário conectado com um conjunto específico de permissões. Se você estiver usando um mecanismo de busca externo, o que geralmente acontece é:
- Executar uma consulta de pesquisa no mecanismo de busca
- Colete os identificadores dos documentos retornados porque nem todo o conteúdo do documento está indexado
- Execute uma consulta para obter os documentos completos
- Se o seu serviço de Query não suporta JOIN, execute outra consulta para obter as permissões herdadas e filtre os documentos
Se quiséssemos tornar as coisas mais complicadas (e talvez também mais reais), poderíamos adicionar uma lógica de cache personalizada a cada etapa. Mas já está complicado o suficiente.
O Couchbase pode fazer tudo em uma única etapa. Em uma única consulta SQL++, podemos pesquisar, selecionar os campos que queremos e fazer JOIN em outros documentos para resolver as permissões. É simples assim. Como o Couchbase é uma plataforma de dados bem integrada, sua linguagem de consulta permite que você aproveite todo o seu poder. Se você tiver interesse, os detalhes poderão vir em um próximo post.
Concluir
Então, o que aprendemos hoje? Usar uma plataforma de dados bem arquitetada pode poupar muito tempo, dinheiro, esforço e dor de cabeça. Porque, no final, você tem menos coisas em que pensar, menos código para escrever, o que significa menos código para manter e uma capacidade mais rápida de entregar para produção. Felizmente, ela também simplifica e economiza em coisas como licenças, treinamento, conformidade e todas aquelas coisas com que gerentes, analistas, seu chefe e o chefe do seu chefe se importam!
- Assista à minha conversa com a RedMonk: O que é Proliferação de Dados? Como Aproveitar uma Plataforma para Controlá-la
- Confira o código do meu exemplo de proliferação de dados
- Saiba mais sobre como Serviços do Couchbase foram projetados para tornar o desenvolvimento suave e simples.
- Experimente o Couchbase Capella DBaaS colocar à prova




Deixe um comentário
Você precisa fazer o login para publicar um comentário.