Let’s look at the performance-related complexities that teams commonly face with write-heavy workloads and discuss your options for tackling them As cargas de trabalho de banco de dados pesadas em escrita apresentam um conjunto de desafios claramente diferente do que as cargas de trabalho pesadas em leitura. Escalar escritos pode ser caro, especialmente se você pagar por operação e escritos são 5X mais caros do que leituras Locking pode adicionar atrasos e reduzir a transmissão As lacunas de I/O podem levar à amplificação de escrita e complicar a recuperação de acidentes Backpressure de banco de dados pode empurrar a carga de entrada Enquanto o custo importa – muito, em muitos casos – não é um tópico que queremos cobrir aqui.Em vez disso, vamos nos concentrar nas complexidades relacionadas ao desempenho que as equipes geralmente enfrentam e discutir suas opções para lidar com elas. O que nós queremos dizer por "uma carga de trabalho pesada de escrita em tempo real"? Primeiro, vamos esclarecer o que queremos dizer por uma carga de trabalho "em tempo real de escrita pesada". Ingere uma grande quantidade de dados (por exemplo, mais de 50K OPS) Envolve mais escritos do que leitores Estão vinculados por SLAs de latência rigorosa (por exemplo, latência de milissegundo de um dígito P99) Na natureza, eles ocorrem em tudo, desde jogos online até bolsas de valores em tempo real. Alguns exemplos específicos: As cargas de trabalho da Internet das Coisas (IoT) tendem a envolver pequenos, mas frequentes anexos de dados de série temporal.Aqui, a taxa de ingestão é determinada principalmente pelo número de endpoints que coletam dados. Os sistemas de logging e monitoramento também lidam com a ingestão frequente de dados, mas eles não têm uma taxa de ingestão fixa. As plataformas de jogos on-line precisam processar interações de usuários em tempo real, incluindo mudanças no estado do jogo, ações do jogador e mensagens.A carga de trabalho tende a ser aguda, com aumentos repentinos de atividade.Eles são extremamente sensíveis à latência, já que até pequenos atrasos podem afetar a experiência de jogo. As cargas de trabalho de comércio eletrônico e varejo são tipicamente pesadas em atualizações e muitas vezes envolvem processamento de lote. Esses sistemas devem manter níveis de inventário precisos, processar comentários de clientes, rastrear o status de pedidos e gerenciar operações de carrinho de compras, que geralmente requerem a leitura de dados existentes antes de fazer atualizações. Os sistemas Ad Tech e Real-time Bidding exigem decisões divididas em segundos. Estes sistemas lidam com o processamento de ofertas complexas, incluindo o rastreamento de impressões e os resultados de leilões, enquanto monitoram simultaneamente as interações do usuário, como cliques e conversões. Os sistemas de bolsa de valores em tempo real devem suportar operações de negociação de alta frequência, atualizações constantes de preços de ações e processos complexos de correspondência de pedidos – tudo mantendo a consistência absoluta dos dados e a latência mínima. Em seguida, vamos olhar para as principais considerações de arquitetura e configuração que afetam o desempenho da escrita. Arquitetura de armazenamento de motores A escolha da arquitetura do motor de armazenamento afeta fundamentalmente o desempenho de escrita em bancos de dados. Existem duas abordagens primárias: árvores LSM e árvores B. Os bancos de dados conhecidos para lidar com escritos de forma eficiente – como ScyllaDB, Apache Cassandra, HBase e Google BigTable – usam Log-Structured Merge Trees (LSM). Esta arquitetura é ideal para lidar com grandes volumes de escritos. Uma vez que os escritos são imediatamente anexados à memória, isso permite um armazenamento inicial muito rápido. Uma vez que a “memtable” na memória se enche, os escritos recentes são lavados para o disco em ordem ordenada. Por exemplo, aqui está o que o caminho de escrita ScyllaDB parece: Com estruturas de árvore B, cada operação de escrita requer a localização e modificação de um nó na árvore – e isso envolve I/O sequencial e aleatório. À medida que o conjunto de dados cresce, a árvore pode exigir nódulos adicionais e reequilíbrio, levando a mais I/O de disco, o que pode afetar o desempenho. Payload tamanho O tamanho da carga útil também afeta o desempenho. Com pequenas cargas úteis, a capacidade de transmissão é boa, mas o processamento da CPU é a principal barreira. À medida que o tamanho da carga útil aumenta, você obtém uma capacidade de transmissão geral menor e a utilização do disco também aumenta. Em última análise, uma pequena escrita normalmente se encaixa em todos os buffers e tudo pode ser processado bastante rapidamente. É por isso que é fácil obter alta capacidade. Para cargas de pagamento maiores, você precisa alocar tampões maiores ou múltiplos buffers. Quanto maiores as cargas de pagamento, mais recursos (rede e disco) são necessários para atender essas cargas de pagamento. Compressão A utilização do disco é algo a ser observado de perto com uma carga de trabalho pesada de escrita.Embora o armazenamento esteja constantemente se tornando mais barato, ainda não é gratuito. A compressão pode ajudar a manter as coisas sob controle – então escolha sua estratégia de compressão com sabedoria. Velocidades de compressão mais rápidas são importantes para cargas de trabalho pesadas de escrita, mas também considere seus recursos de CPU e memória disponíveis. Certifique-se de olhar para o Compressão basicamente divide seus dados em blocos menores (ou pedaços) e, em seguida, comprime cada bloco separadamente. Ao ajustar esta configuração, perceba que pedaços maiores são melhores para leituras, enquanto os menores são melhores para escritos, e considere o tamanho da sua carga útil. Parâmetro de compressão de tamanho Compaixão Para bancos de dados baseados em LSM, a estratégia de compactação que você seleciona também influencia o desempenho de escrita. Compactação envolve a fusão de múltiplos SSTables em arquivos menos, mais organizados, para otimizar o desempenho de leitura, recuperar espaço em disco, reduzir a fragmentação de dados e manter a eficiência geral do sistema. Ao selecionar estratégias de compactação, você pode ter como objetivo a amplificação de baixa leitura, o que torna as leituras tão eficientes quanto possível. Ou, você pode ter como objetivo a amplificação de escrita baixa, evitando que a compactação seja muito agressiva. Ou, você pode priorizar a amplificação de espaço baixo e ter dados de purga de compactação o mais eficientemente possível. (e Cassandra oferece similares): Várias estratégias de compactação Estratégia de compactação de escala de tamanho (STCS): Desencadeada quando o sistema tem suficiente (quatro por padrão) de tamanho semelhante SSTables. Estratégia de compactação nivelada (LCS): O sistema usa pequenos SSTables de tamanho fixo (por padrão 160 MB) distribuídos em diferentes níveis. Estratégia de Compactação Incremental (ICS): Compartilha os mesmos fatores de amplificação de leitura e escrita que o STCS, mas fixa o seu problema de amplificação temporária de espaço 2x, quebrando enormes estátuas em execuções SSTable, que são compostas por um conjunto classificado de SSTables menores (1 GB por padrão), não sobrepostos. Estratégia de compactação de janela do tempo (TWCS): Projetado para dados de série do tempo. Para cargas de trabalho pesadas em escrita, alertamos os usuários para evitar a compactação nivelada a todo custo. Essa estratégia é projetada para casos de uso pesados em leitura. Usá-lo pode resultar em uma lamentável amplificação de escrita de 40x. Batalhão Em bancos de dados como ScyllaDB e Cassandra, batching pode realmente ser um pouco de uma armadilha – especialmente para cargas de trabalho pesadas de escrita. Se você está acostumado com bancos de dados relacionais, batching pode parecer uma boa opção para lidar com um grande volume de escritos. Mas pode realmente abrandar as coisas se não for feito cuidadosamente. Principalmente, isso é porque lotes grandes ou não estruturados acabam criando muita coordenação e rede entre nós. No entanto, isso realmente não é o que você quer em um banco de dados distribuído como ScyllaDB. Aqui está como pensar sobre batching quando você está lidando com escritos pesados: Batch by the Partition Key: Grupar seus escritos pela chave de partição para que o batch vá para um nó de coordenador que também possui os dados. Desta forma, o coordenador não precisa alcançar outros nós para obter dados adicionais. Mantenha baterias pequenas e direcionadas: Dividir grandes baterias em baterias menores por partição mantém as coisas eficientes. Evita sobrecarregar a rede e permite que cada nó trabalhe apenas com os dados que possui. Fique de olho em lotes deslogados: Considerando que você segue os pontos anteriores, é melhor usar lotes deslogados. lotes logados adicionam verificações de consistência adicionais, o que pode realmente retardar a escrita. Então, se você estiver em uma situação difícil de escrever, estruture seus lotes cuidadosamente para evitar os atrasos que grandes lotes de cross-node podem introduzir. Embrulhar Foram fáceis de compilar uma lista de lições aprendidas porque tantas equipes são extremamente bem sucedidas trabalhando com cargas de trabalho pesadas de escrita em tempo real. Se você quiser aprender mais, aqui estão algumas perspectivas de primeira mão de equipes que abordaram desafios bastante interessantes: Zillow: Consumindo registros de vários produtores de dados, o que resultou em escritos fora de ordem que poderiam resultar em atualizações incorretas Tractian: Preparando-se para o crescimento de 10x em dados de alta frequência escritos a partir de dispositivos IoT Fanáticos: Operações pesadas de escrita, como processamento de pedidos, carrinhos de compras e atualizações de produtos para este varejista de esportes on-line Zilhão Traçado Fanáticos Além disso, dê uma olhada no vídeo a seguir, onde vamos entrar ainda mais em profundidade sobre esses desafios pesados de escrita e também passe você por como essas cargas de trabalho parecem no ScyllaDB.