How Coralogix cut processing times from 30 seconds to 86 milliseconds with a PostgreSQL to ScyllaDB migration. A velocidade é importante para , uma plataforma de observação que as equipes de desenvolvimento confiam para detectar incidentes antes que eles se tornem problemas. Coralogix usa um pipeline de análise de streaming em tempo real, fornecendo monitoramento, visualização e capacidades de alerta sem necessidade de indexação. Coralógico Um dos principais diferenciais da Coralogix é um motor de consulta distribuído para consultas rápidas sobre dados mapeados de arquivos de um cliente em armazenamento remoto. Foi originalmente concebido como um mecanismo de consulta sem status acima do armazenamento de objeto subjacente, mas a leitura de metadados Parquet durante a execução da consulta introduziu um impacto de latência inaceitável.Para superar isso, eles desenvolveram um armazenamento de metadados (simplesmente chamado de "metastor") para permitir a recuperação e processamento mais rápidos dos metadados Parquet necessários para executar grandes consultas. Parquinho A implementação original de metastores, construída sobre o PostgreSQL, não foi rápida o suficiente para atender às suas necessidades. Assim, a equipe tentou uma nova implementação – desta vez, com o ScyllaDB em vez do PostgreSQL. Spoiler: Funciona. Eles alcançaram ganhos de desempenho impressionantes – cortando o tempo de processamento de consultas de 30 segundos para 86 milissegundos. E seus engenheiros Dan Harris (Principal Software Engineer) e Sebastian Vercruysse (Senior Software Engineer) tomaram o palco na Cúpula do ScyllaDB para explicar como o fizeram. Junte-se a nós no ScyllaDB Summit 24 para ouvir mais relatórios de primeira mão de como as equipes estão lidando com seus desafios de banco de dados mais difíceis. Disney, Discord, Expedia, Supercell, Paramount e mais estão na agenda. ScyllaDB Summit 2024 é agora um envelope! Update: Metastore Motivação e Requisitos Antes de entrar nos detalhes da implementação de metastores, vamos dar um passo atrás e olhar para a razão para construir uma metastora em primeiro lugar. “Nós inicialmente projetamos esta plataforma como um mecanismo de consulta sem status em cima do armazenamento de objetos subjacente – mas rapidamente percebemos que o custo de ler os metadados do Parquet durante a execução da consulta é uma grande porcentagem do tempo de consulta”, explicou Dan Harris. Eles imaginaram uma solução que seria: Armazenar os metadados do Parquet em um formato decomposto para alta escalabilidade e capacidade Utilize filtros de bloom para identificar de forma eficiente os arquivos a serem digitalizados para cada consulta Use logs de compromisso de transação para adicionar, atualizar e substituir dados existentes no armazenamento de objeto subjacente Os requisitos principais incluíram baixa latência, escalabilidade em termos de capacidade de leitura/escrita e escalabilidade do armazenamento subjacente. gera 2.000 arquivos Parquet por hora (50.000 por dia), totalizando 15 TB por dia, resultando em 20 GB de metadados Parquet sozinho . Um único cliente Por um único dia Um único cliente Por um único dia Implementação inicial do PostgreSQL “Nós começamos a implementação inicial no Postgres, entendendo na época que um motor não distribuído não seria suficiente para o longo prazo”, reconheceu Dan. Essa implementação original armazenava informações-chave como “blocos”, representando um grupo de linha e um arquivo Parquet. Isso inclui metadados como o URL do arquivo, índice de grupo de linha e detalhes mínimos sobre o arquivo. Block url: s3://cgx-production-c4c-archive-data/cx/parquet/v1/team_id=555585/… …dt=2022-12-02/hr=10/0246f9e9-f0da-4723-9b64-a12346095d25.parquet Row group: 0, 1, 2 … Min timestamp Max timestamp Number of rows Total size … Para otimizar a leitura, eles usaram filtros de bloom para cortar dados de forma eficiente. Dan detalhou: “Em última análise, queremos apoiar algo como a pesquisa de texto completo. Basicamente, quando estamos injetando esses arquivos em nosso sistema, podemos construir um filtro de bloom para todos os tokens distintos que encontramos no arquivo. Então, com base em uma consulta específica, podemos usar esses filtros de bloom para cortar os dados que precisamos digitalizar.” Eles armazenaram filtros de bloom em uma configuração de bloco-split, dividindo-os em blocos de 32 bytes para recuperação eficiente. Além disso, eles armazenaram metadados de coluna para cada arquivo Parquet. Block URL Row Group Column Name Column metadata (blob) Dan explicou: “Os arquivos que estamos escrevendo são bastante amplos, às vezes até 20.000 colunas.Então, ao ler apenas os metadados que precisamos, podemos realmente reduzir a quantidade de IO necessária em qualquer consulta dada.” Implementação do ScyllaDB Em seguida, vamos olhar para a implementação do ScyllaDB como descrito pelo colega de equipe de Dan, Sebastian Vercruysse. Blocos de Modelagem de Dados O modelo de bloco teve que ser revisado para a nova implementação. Aqui está um exemplo de um URL de bloco: s3://cgx-production-c4c-archive-data/cx/parquet/v1/team_id=555585/… …dt=2022-12-02/hr=10/0246f9e9-f0da-4723-9b64-a12346095d25.parquet A parte ousada é o balde de nível superior do cliente; dentro do balde, os itens são divididos por hora. Mas alguns clientes têm muitos mais arquivos Parquet do que outros clientes, e eles queriam manter as coisas equilibradas ((Block url, grupo de linha))? Isto identifica de forma única um determinado bloco, mas seria difícil listar todos os blocos para um determinado dia porque o timestamp não está na chave ((Table url, time))? Isso funciona porque se você tem 24 horas para perguntar, você pode perguntar muito facilmente ((Tabel url, hora), bloco url, grupo de linha)? Isso é o que eles escolheram. Ao adicionar o bloco url e grupo de linha como chaves de agrupamento, eles podem facilmente recuperar um bloco específico dentro de uma hora, o que também simplifica o processo de atualização ou exclusão de blocos e grupos de linha. Bloom Filter Chunking e Modelagem de Dados O próximo desafio: como verificar se certos bits estão definidos, dado que o ScyllaDB não oferece funções fora da caixa para isso. A equipe decidiu ler filtros de florescimento e processá-los no aplicativo. No entanto, lembre-se de que eles estão lidando com até 50.000 blocos por dia por cliente, cada bloco contendo 262 KB para a parte do filtro de florescimento. Isso é um total de 12 GB – muito para puxar de volta no aplicativo para uma consulta. Mas eles não precisavam ler o filtro de florescimento inteiro a cada vez; eles precisavam apenas de partes dele, dependendo dos tokens envolvidos durante a execução da consulta. Para a análise de dados, uma das opções é usar como a chave primária. Isso geraria 8192 pedaços de 32 bytes por filtro de florescimento, resultando em uma distribuição uniforme com cerca de 262 KB por partição. Com cada filtro de florescimento na mesma partição, seria fácil inserir e excluir dados com uma única consulta de lote. Mas há uma captura que afeta a eficiência de leitura: você precisaria saber a ID do bloco antes de poder ler o filtro de florescimento. Além disso, a abordagem envolveria o acesso a um número substancial de partições; blocos 50K significam partições 50K. E como Sebastian observou, “Mesmo com algo tão rápido como ScyllaDB, ainda é difícil alcançar o processo de sub-segundo para partições 50K.” ((block_url, row_group), índice do bloco) Outra opção (a que eles finalmente decidiram): Observe que esta é a mesma chave de partição que a chave Blocks, com um índice adicionado à chave de partição que representa o token nth exigido pelo mecanismo de consulta.Com esta abordagem, a varredura de 5 tokens que abrangem uma janela de 24 horas resulta em 120 partições – uma melhoria impressionante em comparação com a opção de modelagem de dados anterior. (URL da tabela, hora, índice do pedaço), URL do bloco, grupo da linha) Além disso, esta abordagem não requer mais o ID de bloco antes de ler o filtro de florescimento – permitindo leituras mais rápidas. Claro, sempre há compromissos. Aqui, devido à abordagem de filtro de florescimento bloqueado, eles têm que dividir um único filtro de florescimento em 8192 partições únicas. Isso acaba afetando a velocidade de ingestão em comparação com a abordagem de partição anterior que permitiu ingerir todos os pedaços de filtro de florescimento de uma só vez. No entanto, a capacidade de ler rapidamente um determinado bloco dentro de uma hora é mais importante para eles do que as letras rápidas – então eles decidiram que este compromisso valeu a pena. Modelagem de dados doença Não surpreendentemente, a mudança de SQL para NoSQL envolveu uma quantidade razoável de reworking de modelagem de dados, incluindo alguns ensaios e erros. Por exemplo, Sebastian compartilhou: “Um dia, eu descobri que tínhamos confundido os timestamps min e max – e eu me perguntei como eu ia corrigir isso. Eu pensei que talvez eu poderia renomear as colunas e, de alguma forma, fazê-lo funcionar novamente. Mas, aqui você não pode renomear uma coluna se ela for parte de uma chave de agrupamento. Eu pensei que eu poderia certamente adicionar novas colunas e executar uma consulta UPDATE para atualizar todas as linhas. No final, eles decidiram cortar a tabela e começar de novo versus escrever código de migração. Desempenho ganha Apesar do trabalho de modelagem de dados necessário, a migração pagou bem. Cada nodo atualmente lida com 4-5 TB. Eles estão atualmente processando cerca de 10K escritos por segundo com latência P99 consistentemente abaixo de um milissegundo. A lista de blocos resulta em cerca de 2000 arquivos de parquet em uma hora; com seus filtros de florescimento, eles são processados em menos de 20 milissegundos. Para arquivos de 50K, é menos de 500 milissegundos. Mas, para arquivos 50K Parquet, 500 milissegundos é bom para suas necessidades. No processamento de metadados de coluna, o P50 é bastante bom, mas há uma alta latência de cauda. Sebastian explicou: “O problema é que se temos arquivos 50K Parquet, nossos executores estão coletando todos estes em paralelo. Configuração do ScyllaDB Notavelmente, o Coralogix mudou-se da primeira descoberta do ScyllaDB para entrar em produção com terabytes de dados em apenas 2 meses (e esta foi uma migração SQL para NoSQL que exigia trabalho de modelagem de dados, não uma migração muito mais simples Cassandra ou DynamoDB). A implementação foi escrita em Rust em cima do E eles encontraram , em e Uma vez que oferecer aos seus próprios clientes uma alternativa de observação de baixo custo é importante para a Coralogix, a equipe da Coralogix ficou satisfeita com o desempenho favorável do preço da sua infraestrutura ScyllaDB: um cluster de 3 nós com: ScyllaDB Rust motorista Operador ScyllaDB para Kubernetes Monitoramento ScyllaDB Gerenciador ScyllaDB 8 VCPU 32 GB de memória Arma / Gravitação Volumes EBS (gp3) com largura de banda de 500 MBps e 12k IOPS Usando ARM reduz custos, e a decisão de usar volumes EBS (gp3) acabou por se reduzir a disponibilidade, flexibilidade e desempenho de preço. Lições aprendidas As principais lições aprendidas aqui... A maior diferença em trabalhar com ScyllaDB versus trabalhar com Postgres é que você tem que pensar bastante cuidadosamente sobre sua partição e tamanhos de partição. Keep an eye on partition sizes: Você também tem que pensar cuidadosamente sobre padrões de leitura/escrita. sua carga de trabalho é de leitura pesada? envolve uma boa mistura de leitura e escrita? ou, é predominantemente de escrita pesada? as cargas de trabalho da Coralogix são bastante de escrita pesada porque eles estão constantemente ingerindo dados, mas eles precisam priorizar as leituras porque a latência de leitura é mais crítica para seu negócio. Think about read/write patterns: A equipe admite que eles foram avisados para não usar o EBS: “Não ouvimos, mas provavelmente deveríamos.Se você está considerando usar o ScyllaDB, provavelmente seria uma boa idéia olhar para instâncias que têm SSDs locais em vez de tentar usar volumes do EBS.” Avoid EBS: Planos para o futuro: WebAssembly UDFs com Rust No futuro, eles querem encontrar o meio-termo entre escrever pedaços suficientemente grandes e ler dados desnecessários.Estão dividindo os pedaços em ~8.000 linhas e acreditam que podem dividí-los ainda mais em 1.000 linhas, o que poderia acelerar suas inserções. Seu objetivo final é descarregar ainda mais trabalho para o ScyllaDB, aproveitando Com seu código Rust existente, a integração de UDFs eliminaria a necessidade de enviar dados de volta para o aplicativo, proporcionando flexibilidade para ajustes e possíveis melhorias. Funções Definidas pelo Usuário (UDFs) com o WebAssembly Sebastian compartilha: “Já temos tudo escrito em Rust. Seria muito bom se pudéssemos começar a usar os UDFs para que não tivéssemos que enviar nada de volta para o aplicativo. Assista ao Discurso Técnico completo Você pode assistir a conversa de tecnologia completa e esquiar através do deck em nossa biblioteca de conversa de tecnologia. Sobre Cynthia Dunlop Cynthia é Diretora Sênior de Estratégia de Conteúdo na ScyllaDB. Ela escreve sobre desenvolvimento de software e engenharia de qualidade há mais de 20 anos.