<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joaquim Chianca</title>
    <description>The latest articles on DEV Community by Joaquim Chianca (@joaquimchianca).</description>
    <link>https://dev.to/joaquimchianca</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F853890%2Ff710642b-598b-406f-91f0-eff0e7b3b64f.jpeg</url>
      <title>DEV Community: Joaquim Chianca</title>
      <link>https://dev.to/joaquimchianca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joaquimchianca"/>
    <language>en</language>
    <item>
      <title>DynamoDB: Como implementar sistemas resilientes e distribuídos</title>
      <dc:creator>Joaquim Chianca</dc:creator>
      <pubDate>Tue, 28 Jan 2025 17:43:12 +0000</pubDate>
      <link>https://dev.to/joaquimchianca/dynamodb-como-implementar-sistemas-resilientes-e-distribuidos-dl1</link>
      <guid>https://dev.to/joaquimchianca/dynamodb-como-implementar-sistemas-resilientes-e-distribuidos-dl1</guid>
      <description>&lt;p&gt;No contexto de sistemas distribuídos, a escolha do banco de dados é decisão crucial para o desempenho, escalabilidade e disponibilidade da aplicação. O &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;, criado pela AWS, destaca-se como uma solução poderosa e flexível para desenvolvedores que precisam de bancos altamente escaláveis e distribuídos. Ele permite o processamento de grandes volumes de dados com baixa latência, ideal para aplicações globais e sensíveis ao desempenho.&lt;/p&gt;

&lt;p&gt;Nesse artigo, exploraremos como o DynamoDB implementa o conceito de &lt;strong&gt;consistência eventual (eventual consistency)&lt;/strong&gt;, modelo de consistência amplamente utilizado em sistemas distribuídos.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o DynamoDB?
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt; é um banco de dados NoSQL totalmente gerenciado, desenvolvido pela Amazon Web Services (AWS). Projetado para aplicações que exigem alto desempenho. Suas principais características são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dados orientados em tabela, com suporte para chave-valor&lt;/strong&gt;: Permite armazenar dados em estruturas flexíveis, com suporte a documentos JSON e tabelas distribuídas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidade automática&lt;/strong&gt;: Garante que o banco de dados se ajuste automaticamente às necessidades de aplicações de qualquer tamanho.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alta disponibilidade&lt;/strong&gt;: Replica dados automaticamente em múltiplas zonas de disponibilidade. Utiliza sharding automático para distribuir o dados em múltiplas partições, baseando-se em chave primária.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consultas complexas&lt;/strong&gt;: Suporta índices secundários globais e locais para facilitar consultas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Foi introduzido em 2012, como uma evolução do Amazon SimpleDB, com objetivo de fornecer um banco de dados otimizado para aplicações modernas, como e-commerces, IoT e jogos. Tais aplicações requerem escalabilidade global e consistência em sistemas distribuídos. &lt;/p&gt;

&lt;p&gt;O DynamoDB possui foco em resolver problemas comuns de bancos de dados relacionais, como limitação de escalabilidade e gargalos em transações complexas. Sua arquitetura é fundamentada na distribuição de dados em partições que podem ser gerenciadas de forma independente, o que permite alta disponibilidade e baixíssima latência.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teorema CAP e Eventual Consistency
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Teorema CAP&lt;/strong&gt;  estabelece que um sistema distribuído pode garantir, no máximo, dois dos três atributos a seguir:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistência (C)&lt;/strong&gt;: Todos os nós veem os mesmos dados ao mesmo tempo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disponibilidade (A)&lt;/strong&gt;: O sistema responde a todas as solicitações, mesmo que nem todos os nós estejam funcionando.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tolerância a Particionamento (P)&lt;/strong&gt;: O sistema continua funcionando mesmo quando há falhas ou perda de comunicação entre nós.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A nível de contexto, existem três tipos de consistência:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistência Forte&lt;/strong&gt;: As atualizações são imediatamente visíveis para todas as leituras em todos os nós.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistência Eventual&lt;/strong&gt;: As atualizações são propagadas aos nós de forma assíncrona, e o sistema atinge consistência em um momento futuro. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistência Causal&lt;/strong&gt;: Garante ordem em operações dependentes, mas não em todas operações.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Os sistemas distribuídos possuem natureza inerente à partição - são feitos para funcionar mesmo que algum nó não esteja funcionando - resultando em uma escolha entre disponibilidade ou consistência. O DynamoDB opta pela disponibilidade, uma vez que para um banco, na maioria das vezes, é mais interessante que haja uma resposta para toda consulta do que os dados estarem atualizados em todos os nós. Por isso, o banco implementa uma lógica para consistência denominada de &lt;strong&gt;consistência eventual&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Parece um pouco controverso que um banco de dados nem sempre esteja com todos os nós atualizados o tempo todo, afinal imagine quantos problemas podem ser provocados por respostas não atualizadas, entretanto a maneira como é implementada a consistência no DynamoDB permite o uso dessa ferramenta em sistemas globais, onde a latência é crítica e deve existir tolerância a falhas. A consistência eventual resulta em maior escalabilidade, já que não é necessária constante sincronização entre nós, o que abre portas para uma escalabilidade horizontal.&lt;/p&gt;

&lt;p&gt;A imagem abaixo ilustra bem como funciona a consistência eventual: em que a escrita é feita num nó primário e os dados são sincronizados para os demais nós após um determinado período de tempo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rt6bxm4dqlziczy49wk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rt6bxm4dqlziczy49wk.png" alt="consistência no dynamodb" width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparando Consistência Eventual no DynamoDB e Outros Bancos
&lt;/h2&gt;

&lt;p&gt;Embora a consistência eventual seja um conceito comum em sistemas distribuídos, sua implementação varia entre bancos de dados. O DynamoDB se destaca por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Tables&lt;/strong&gt;: Replicam dados automaticamente em várias regiões, garantindo consistência eventual sem necessidade de configuração manual. Em contraste, no Apache Cassandra, a replicação entre data centers requer configurações manuais detalhadas, incluindo a definição de estratégias de replicação e o gerenciamento de topologias de rede. O CouchDB, embora suporte replicação, não oferece uma solução integrada para replicação global automática, exigindo configurações adicionais e gerenciamento manual para alcançar um comportamento semelhante.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DynamoDB Streams&lt;/strong&gt;: Permitem capturar mudanças nos dados e propagar atualizações de forma eficiente. Isso é particularmente útil para disparar eventos, atualizar caches ou sincronizar com outros sistemas. No Cassandra, funcionalidades semelhantes podem ser implementadas usando o Commit Log ou ferramentas adicionais, mas geralmente requerem configurações extras e não são tão integradas quanto no DynamoDB. O CouchDB possui um mecanismo de changes feed que permite acompanhar alterações, mas pode não oferecer a mesma eficiência e integração que o DynamoDB Streams proporciona.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modelos de consistência configuráveis&lt;/strong&gt;: O DynamoDB oferece aos desenvolvedores a flexibilidade de escolher entre leituras com consistência eventual (padrão) e leituras com consistência forte, dependendo das necessidades específicas da aplicação. No Cassandra, embora seja possível ajustar o nível de consistência para operações de leitura e escrita, isso requer um entendimento aprofundado da arquitetura do cluster e configurações manuais para cada operação. O CouchDB, por sua vez, adota uma abordagem de consistência eventual por padrão e não oferece suporte nativo para leituras com consistência forte, limitando as opções para aplicações que necessitam de garantias de consistência mais rígidas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Embora Cassandra e CouchDB também implementem consistência eventual, o DynamoDB se destaca por fornecer ferramentas integradas e configuráveis que simplificam o desenvolvimento de aplicações distribuídas e resilientes. As Global Tables e o DynamoDB Streams oferecem funcionalidades avançadas de replicação e processamento de eventos que facilitam a construção de sistemas globais com alta disponibilidade e desempenho consistente.&lt;/p&gt;

&lt;p&gt;Sem falar que tudo isso é gerenciado pela AWS, com o foco em trazer todas vantagens de um banco NoSQL com a simplicidade no processo de configuração.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarking: Amazon DynamoDB vs Google Cloud Datastore
&lt;/h2&gt;

&lt;p&gt;Nessa seção, vou ilustrar um cenário comparativo entre dois bancos NoSQL: DynamoDB e Google Cloud Datastore, ambos possuem basicamente o mesmo objetivo em um sistema distribuído: alta disponibilidade com baixa latência.&lt;/p&gt;

&lt;p&gt;A comparação se dará através das métricas vazão média e latência entre os dois bancos em diferentes workloads. Além disso o cliente para cada um dos bancos vai ser tanto o Google Compute Engine e o AWS EC2. A imagem abaixo ilustra o experimento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9fdrpx5kdvap8jqzp9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9fdrpx5kdvap8jqzp9j.png" alt="experimento" width="503" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workloads utilizados e operações no banco&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Workload A: 95% read, 5% update (teste de leitura)&lt;/li&gt;
&lt;li&gt;Workload B: 50% read, 50% update (teste balanceado)&lt;/li&gt;
&lt;li&gt;Workload C: 5% read, 95% update (teste de escrita)&lt;/li&gt;
&lt;li&gt;Workload D: 70% read, 15% update, 15% insert (cenário especial de teste)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O estudo foi feito durante uma semana, rodando cada um dos workloads duas vezes (uma utilizando o EC2 e outra usando o Compute Engine). Mais detalhes &lt;a href="https://medium.com/@wattanai.tha/nosql-cloud-service-benchmarking-dynamodb-vs-datastore-3f57b6951fb" rel="noopener noreferrer"&gt;nesse artigo em inglês&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultados e conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboh9fh80yvpntburc73w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboh9fh80yvpntburc73w.png" alt="resultados experimento" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqcvvp3nc8v7n60qxnqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqcvvp3nc8v7n60qxnqg.png" alt="resultados experimento" width="724" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv3p34ikqh6l8vgmcloq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv3p34ikqh6l8vgmcloq.png" alt="resultados experimento" width="720" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm76gdii1lo2hcb2lgv02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm76gdii1lo2hcb2lgv02.png" alt="resultados experimento" width="707" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierqm5jiyixl9fax8tj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierqm5jiyixl9fax8tj.png" alt="resultados experimento" width="683" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46e9y8tskywdwasuosh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46e9y8tskywdwasuosh0.png" alt="resultados experimento" width="724" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foa15izudd25w6gcurtdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foa15izudd25w6gcurtdp.png" alt="resultados experimento" width="730" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpibzigoyo1u75f7cgby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpibzigoyo1u75f7cgby.png" alt="resultados experimento" width="716" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O DynamoDB possui significativamente vazão média maior e latência menor em todos workloads, comparado ao Cloud Datastore, o que consequentemente proporciona uma melhor performance. &lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso do DynamoDB
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Jogos&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O setor de jogos frequentemente envolve padrões de leitura e gravação altamente concorrentes, especialmente em jogos online multijogador massivos, onde milhares ou até milhões de jogadores podem acessar servidores de jogos simultaneamente. O servidor precisa ser capaz de lidar com as requisições de leitura e gravação de jogadores distribuídos globalmente em tempo real.&lt;/p&gt;

&lt;p&gt;O DynamoDB é ideal para esse caso de uso, pois se escala facilmente por várias regiões globais, mantendo a latência de leitura e gravação em milissegundos de uma única casa decimal.&lt;/p&gt;

&lt;p&gt;Empresas como Capcom, PennyPop e Electronic Arts utilizam o DynamoDB para escalar aplicações de jogos. &lt;a href="https://aws.amazon.com/pt/blogs/database/amazon-dynamodb-gaming-use-cases-and-design-patterns/" rel="noopener noreferrer"&gt;Você pode aprender mais sobre os casos de uso e padrões de design do DynamoDB no setor de jogos.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Streaming de Conteúdo&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aplicações de streaming de conteúdo precisam ser altamente disponíveis e escaláveis, utilizando implementações multi-AZ (zonas de disponibilidade) para atender a audiências globais. O streaming de conteúdo também está sujeito a tráfego desigual ou picos repentinos, por isso, essas aplicações se beneficiam de modelos de computação serverless que escalam conforme a demanda.&lt;/p&gt;

&lt;p&gt;O DynamoDB é um ótimo banco de dados para aplicações de streaming de conteúdo devido à sua capacidade de replicar dados globalmente e oferecer balanceamento de carga flexível para acomodar mudanças na audiência.&lt;/p&gt;

&lt;p&gt;Empresas como Netflix, Hulu e Disney utilizam o DynamoDB para dar suporte às suas aplicações de streaming de conteúdo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Bancos e Finanças&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Transações financeiras acontecem em tempo real, e os aplicativos móveis são a experiência padrão para serviços bancários. Os clientes esperam poder gerenciar seu dinheiro a partir de seus telefones e fazer isso em tempo real. Bancos precisam processar muitas requisições simultâneas de clientes globais, mantendo as transações financeiras seguras e atualizadas.&lt;/p&gt;

&lt;p&gt;O DynamoDB é ideal para o setor bancário porque pode lidar com a escala global e os padrões rápidos de leitura/gravação necessários para manter as informações financeiras atualizadas tanto no servidor quanto na aplicação voltada para o usuário. Além disso, oferece leituras fortemente consistentes mesmo em arquiteturas distribuídas, garantindo que os dados financeiros sejam precisos e atualizados.&lt;/p&gt;

&lt;p&gt;Empresas como Capital One, Robinhood e PayPay utilizam o DynamoDB para reduzir a latência em seus aplicativos móveis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Aplicativos Móveis e Web&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Em diversos setores, incluindo os acima mencionados, aplicativos web e móveis atendem muitos usuários simultaneamente em tempo real.&lt;/p&gt;

&lt;p&gt;Por todas as razões descritas, o DynamoDB é um banco de dados perfeito para apoiar aplicativos web e móveis construídos dentro do ecossistema AWS. Ele pode escalar para lidar com tráfego flutuante e oferece flexibilidade para maximizar a taxa de transferência sem custos elevados.&lt;/p&gt;

&lt;p&gt;Empresas como Duolingo, AirBnB e Tinder utilizam o DynamoDB para construir aplicativos web e móveis rápidos e escaláveis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Internet das Coisas (IoT)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Casos de uso da IoT envolvem gravações frequentes e através de um throughput imprevisível, à medida que dispositivos distribuídos globalmente geram fluxos de dados em tempo real.&lt;/p&gt;

&lt;p&gt;Embora o DynamoDB não seja estritamente um banco de dados de séries temporais, ele pode ser usado de forma eficaz em aplicações de IoT, especialmente quando combinado com outras ferramentas AWS, como o IoT Core, Lambda e Kinesis.&lt;/p&gt;

&lt;p&gt;Empresas como BMW, GE e Verizon utilizam o DynamoDB para processar dados da IoT.&lt;/p&gt;

&lt;p&gt;Mais informações sobre casos de usos na indústria &lt;a href="https://www.youtube.com/watch?v=Pu6y1peXoko" rel="noopener noreferrer"&gt;neste vídeo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O Amazon DynamoDB se estabelece como uma solução poderosa e flexível para sistemas distribuídos que exigem escalabilidade, baixa latência e alta disponibilidade. Seu suporte à consistência eventual permite que seja altamente eficiente em ambientes globais, com tolerância a falhas e capacidade de gerenciar grandes volumes de dados em tempo real.&lt;/p&gt;

&lt;p&gt;Ao optar pela consistência eventual, o DynamoDB garante uma escalabilidade superior, permitindo que os dados sejam propagados entre nós de forma assíncrona, com a aplicação atingindo a consistência no futuro, o que é ideal para aplicações que necessitam de disponibilidade contínua. Essa abordagem é essencial para grandes sistemas distribuídos, como jogos online, streaming de conteúdo, finanças e IoT, onde a baixa latência e a capacidade de escalar conforme a demanda são cruciais.&lt;/p&gt;

&lt;p&gt;Além disso, o DynamoDB se destaca pela simplicidade em sua configuração e gerenciamento, principalmente por ser totalmente gerido pela AWS. Funcionalidades como Global Tables e DynamoDB Streams permitem replicação automática e eficiente, enquanto os modelos de consistência configuráveis fornecem flexibilidade para atender a diferentes necessidades das aplicações.&lt;/p&gt;

</description>
      <category>dynamodb</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Flyway e Spring Boot em cenário de banco de dados não vazio.</title>
      <dc:creator>Joaquim Chianca</dc:creator>
      <pubDate>Sat, 27 Apr 2024 07:39:58 +0000</pubDate>
      <link>https://dev.to/joaquimchianca/flyway-e-spring-boot-em-cenario-de-banco-de-dados-nao-vazio-2f57</link>
      <guid>https://dev.to/joaquimchianca/flyway-e-spring-boot-em-cenario-de-banco-de-dados-nao-vazio-2f57</guid>
      <description>&lt;p&gt;Em um projeto de programação, em que estava construindo uma API com Spring Boot (Java), precisei adicionar alguns records numa tabela do meu banco de dados. Devido ao meu repertório e também buscando me desafiar, adicionei a dependência do Flyway para adicionar migrações ao meu banco de dados. &lt;strong&gt;Entretanto, ao adicionar o Flyway num projeto existente, ocorreram alguns comportamentos inesperados.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas, calma, tô voando.. O que é o Flyway?
&lt;/h2&gt;

&lt;p&gt;Basicamente, o Flyway serve de versionamento de banco de dados. Suponha que existem 3 programadores rodando o mesmo projeto num ambiente de desenvolvimento. O ideal é que o banco de dados de todos (mesmo que em ambientes diferentes) possuam as mesmas tabelas.&lt;/p&gt;

&lt;p&gt;Por meio de vários arquivos &lt;code&gt;.sql&lt;/code&gt;, o Spring detecta a existência desses arquivos, roda o script SQL antes mesmo de criar as tabelas com o Hibernate. Assim, podemos criar arquivos &lt;code&gt;.sql&lt;/code&gt; para criar as tabelas necessárias para o funcionamento correto da aplicação, garantindo que as tabelas possuem o mesmo formato para cada ambiente de desenvolvimento diferente. Uma forma de padronizar e manter o banco de dados atualizado para todos do time.&lt;/p&gt;

&lt;h2&gt;
  
  
  E Hibernate?
&lt;/h2&gt;

&lt;p&gt;Hibernate é uma implementação da JPA (Java Persistence API), responsável pela ponte entre a sua aplicação e seu banco de dados. Todo método default do &lt;code&gt;repository&lt;/code&gt; é implementado pelo Hibernate. O Hibernate também é o responsável por criar suas tabelas das entidades do seu projeto (classes anotadas com o &lt;code&gt;@Entity&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;O Hibernate já cria minhas tabelas, por qual razão eu preciso do Flyway?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como já comentado acima, o Flyway é usado para padronizar as tabelas do seu projeto. Dessa forma, o Spring executa as migrações do Flyway antes mesmo de executar o Hibernate, logo, o ideal é que o time defina muito bem essas tabelas por meio de arquivos &lt;code&gt;.sql&lt;/code&gt; no projeto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A boa prática é criar as migrations antes mesmo de criar qualquer classe dentro do seu projeto.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adicionando Flyway a um projeto existente
&lt;/h2&gt;

&lt;p&gt;A motivação de escrever esse arquivo veio quando tentei adicionar o Flyway ao meu projeto que já possuía as tabelas mapeadas para cada entidade, criadas através do Hibernate.&lt;/p&gt;

&lt;p&gt;Minha ideia era usar o Flyway apenas para inserir records numa tabela já existente, porém notei que as inserções não estavam acontecendo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dissecando o problema
&lt;/h3&gt;

&lt;p&gt;Primeiro, fui atrás de criar novas migrations no projeto, para ter certeza de que o Flyway estava configurado corretamente e funcionando quando eu criava novas tabelas. E sim, ele funcionara corretamente quando foi criada uma tabela exemplo arbitrária.&lt;/p&gt;

&lt;p&gt;Tendo em mente que o problema não estava na configuração da dependência externa, fui atrás de saber como funciona o relacionamento do Flyway com o Hibernate. &lt;strong&gt;O interessante (como já foi comentado nesse artigo) foi descobrir que o Flyway é executado antes do Hibernate.&lt;/strong&gt; Dessa forma, era óbvio que minha lógica não funcionaria, afinal, como eu posso inserir records numa tabela que ainda não foi carregada pelo Hibernate?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O problema estava exatamente nessa ordem de execução das dependências.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolução
&lt;/h3&gt;

&lt;p&gt;Bastou criar uma classe de configuração do Flyway para que fosse carregado o conteúdo do Hibernate antes do próprio Flyway. Para isso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defini a propriedade &lt;code&gt;spring.flyway.enabled=false&lt;/code&gt; no &lt;code&gt;application.properties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Criei uma classe de configuração Flyway &lt;code&gt;FlywayConfig.java&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlywayConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;FlywayConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Flyway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baselineVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baselineOnMigrate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O próprio Spring injeta o dataSource nesse construtor do Flyway, indicando que ele deve carregar primeiro o banco de dados &lt;code&gt;.dataSource(dataSource).load()&lt;/code&gt; e apenas depois executar a migração, por meio do método &lt;code&gt;migrate()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Feito isso, criei uma nova migration com inserção de records &lt;code&gt;V4__insert_user.sql&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;tb_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'zeldris@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'zeldris'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'zeldris'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'zeldris'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E voilà, a record está inserida na minha tabela:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkf3xpa6xixiflcm222t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkf3xpa6xixiflcm222t9.png" alt="tela mostrando a inserção" width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O intuito desse artigo é compartilhar essa noção de funcionamento das duas dependências que lidam com banco de dados: Hibernate e Flyway, além de ajudar aqueles que estão com o projeto existente e passam pela mesma situação de mal funcionamento das migrations da ferramenta.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Como escrever uma mensagem de commit</title>
      <dc:creator>Joaquim Chianca</dc:creator>
      <pubDate>Thu, 10 Aug 2023 20:45:22 +0000</pubDate>
      <link>https://dev.to/joaquimchianca/como-escrever-uma-mensagem-de-commit-4208</link>
      <guid>https://dev.to/joaquimchianca/como-escrever-uma-mensagem-de-commit-4208</guid>
      <description>&lt;p&gt;Como programadores, dar nomes para as coisas (variáveis, funções, etc) faz parte da nossa rotina diária. Em linguagens de programação temos que seguir uma convenção, isto é, um modelo para nomear &lt;strong&gt;e isto também se aplica para as mensagens de commit no Github.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;É bem difícil colocar em mais ou menos 50 caracteres as mudanças feitas no seu código. Quando não se está acostumado com as boas práticas, você adiciona uma nova feature, faz refatoração de código, cria novos testes unitários para suas funções e coloca tudo isso dentro de um mesmo commit e faz o push pro seu repositório no Github.&lt;/p&gt;

&lt;h3&gt;
  
  
  O grande macete é pensar nos seus commits como checkpoints do seu código.
&lt;/h3&gt;

&lt;p&gt;Como num jogo, toda vez que você ganha um novo item, ou derrota um boss é interessante você salvá-lo, para não perder o progresso. O mesmo vale para seu código e seus commits.&lt;/p&gt;

&lt;p&gt;Por exemplo, criados novos testes, faça um commit com a mensagem &lt;code&gt;test: criação de testes unitários para função X&lt;/code&gt;. Percebe que além de uma mensagem clara, resumindo o que foi feito naquele commit, temos um nome identificando qual é o &lt;strong&gt;tipo de commit.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Peraí, commits possuem tipos?
&lt;/h3&gt;

&lt;p&gt;Não necessariamente você é obrigado a colocar os tipos, porém em projetos open-source é comum essa prática, visto que muitos desenvolvedores estão contribuindo para o repositório e é necessária uma organização.&lt;/p&gt;

&lt;p&gt;Considere o repositório do framework Angular, ferramenta a qual permite criar componentes visuais com Javascript de maneira mais automática:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxdz1rcyi9hqqjwnaxbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxdz1rcyi9hqqjwnaxbd.png" alt="repositório angular"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dentro do próprio repositório existe um &lt;a href="https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines" rel="noopener noreferrer"&gt;arquivo&lt;/a&gt;, em inglês, ensinando os desenvolvedores como escrever a mensagem de commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quais são os tipos?
&lt;/h3&gt;

&lt;p&gt;Os tipos mais importantes, sem dúvidas, são &lt;strong&gt;fix&lt;/strong&gt; e &lt;strong&gt;feat&lt;/strong&gt;. O primeiro serve para denotar correção de bugs no código, enquanto o segundo define uma nova funcionalidade no código.&lt;/p&gt;

&lt;p&gt;Além disso, temos outros tipos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;chore&lt;/strong&gt;: mudanças que não estão ligadas à funcionalidade do projeto, mas necessárias para que o projeto funcione (manutenção de arquivos de integração contínua, processos de compilação). Basicamente, infraestrutura do código&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs&lt;/strong&gt;: commits relacionados à documentação apenas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;perf&lt;/strong&gt;: mudanças referentes à performance do código&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;style&lt;/strong&gt;: estilização do código (adição de novas linhas em branco, indentação)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;refactor&lt;/strong&gt;: refatoração de código, não corrige bugs e nem adiciona novas funcionalidades&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;test&lt;/strong&gt;: correção de testes ou criação de novos testes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Outros fatores importantes
&lt;/h3&gt;

&lt;p&gt;Existem mais especificações sobre qual a maneira correta de um commit, por exemplo, definir o escopo de onde ocorreu a mudança: &lt;code&gt;fix(api): correção de bug na criação de usuário&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Contudo, o essencial é separar os commits em tipos, isso já deixa o ambiente muito mais organizado e a adição do escopo na mensagem só deve ser feita, caso o projeto seja complexo, ou se for instrução da empresa ou time em que se está trabalhando.&lt;/p&gt;

&lt;p&gt;Além disso, &lt;strong&gt;eu desaconselho&lt;/strong&gt; colocar emojis nas mensagens de commit, porque polui visualmente e - na maioria dos casos - confunde outros desenvolvedores.&lt;/p&gt;

&lt;p&gt;Em suma, o mais importante é deixar claro o que foi feito no commit, para que outros possam entender como o projeto está evoluindo.&lt;/p&gt;

&lt;p&gt;Se desejar entrar em contato: &lt;a href="https://www.linkedin.com/in/joaquim-chianca/" rel="noopener noreferrer"&gt;meu linkedin&lt;/a&gt;. Estou à disposição para networking.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>braziliandevs</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
