Produto e engenharia
Companhia
Produto e engenharia
Companhia
November 18, 2021
10 minutos

Implementando um pipeline de dados de streaming

Trustly

Trustly teve um grande crescimento nos últimos anos e isso afetou a forma como fazemos dados e análises. Nossos desafios provavelmente não são únicos e ainda não sabemos se as escolhas que fizemos foram as corretas. Só o tempo dirá. Estou na empresa há quase seis anos e vi nossos recursos dedicados de dados e análises crescerem de zero para talvez 40 pessoas, dependendo de como você nos conta. Daqui a um ano, esse número terá crescido ainda mais.

Plano de fundo

Originalmente, pretendia que esta postagem do blog fosse bastante técnica e se concentrasse apenas em alguns desafios explícitos de engenharia que enfrentamos e em como os resolvemos. Mas logo percebi que não faria muito sentido se eu não descrevesse um pouco mais o contexto. Uma coisa que notei ao fazer parte de uma organização maior é que se torna ainda mais importante manter o foco nos problemas que você está tentando resolver. Como engenheiro, me sinto melhor quando posso passar um dia inteiro tentando resolver um problema técnico interessante (e provavelmente não sou o único). Como ser humano, costumo gravitar em torno de fazer coisas que me façam sentir bem (não é verdade?). Infelizmente, o que me faz sentir bem nem sempre é o que é mais valioso para meu empregador. Em uma pequena organização em que todos se conhecem e todos os funcionários almoçam juntos às segundas-feiras, esse desalinhamento rapidamente se torna óbvio e pode ser resolvido, mas quanto maior a organização se torna, mais eu posso continuar resolvendo problemas que talvez não fossem tão importantes no início. É mais difícil - para mim e para os outros - falsificar minha crença de que estou trabalhando em algo realmente importante. Especialmente quando parece que algo que um engenheiro de dados deveria estar fazendo, como criar um pipeline de dados de streaming.

Primeiro, vamos dar uma olhada em uma de nossas plataformas de dados em lote existentes, que usa o Google Cloud Platform. Temos várias fontes de dados, das quais a mais importante é nosso produto de pagamento, mas também inclui sistemas de CRM, sistemas financeiros, Jira etc. A maioria dos dados é extraída desses sistemas usando trabalhos escritos em Python e acionados pelo Airflow. Ingerimos todos esses dados e os colocamos em um formato bastante bruto no BigQuery, nosso data lake, se você quiser. As transformações a partir daí são escritas em SQL e executadas pelo dbt. Começamos há alguns anos orquestrando todas essas transformações de SQL com operadores do Airflow, mas mudamos tudo para o dbt há cerca de um ano e não nos arrependemos disso nem por um minuto. O Dbt funciona muito bem e nos permite dissociar a transformação dos dados da ingestão.

Ao mudar de uma organização pequena para uma maior, você precisa começar a pensar em processos de dissociação e em como escalar suas equipes. Quando toda a organização de dados tiver apenas três pessoas, todos saberão um pouco de tudo — e tudo bem. Se você quiser escalar isso 10 vezes, a melhor maneira de fazer isso provavelmente não é exigir que cada novo membro da equipe conheça Java, Python, SQL e arquitetura em nuvem, além de ter uma compreensão detalhada de quais métricas de produto são importantes, em qual sistema de origem encontrar os dados brutos, como defini-los e como trabalhar com as partes interessadas da empresa. Pessoas que sabem tudo isso (ou podem até mesmo aprender) são um recurso escasso. Em vez disso, permitir que analistas e engenheiros de análise desenvolvam e mantenham pipelines em SQL, sem precisar se preocupar com a forma como os dados brutos chegam à plataforma em primeiro lugar — uma tarefa que é melhor deixar para os engenheiros de dados — é algo que descobrimos que nos permite remover gargalos e distribuir as cargas de trabalho entre várias equipes.

Por que fazer streaming?

Então, voltando ao streaming - por que precisamos disso? A resposta óbvia seria que precisamos de dados em tempo real e, embora isso seja certamente algo pelo qual nos esforçar, eu não diria que é o que mais importa para nós no momento. Tudo o resto sendo igual - ter dados, ou seja, saber alguma coisa, mais cedo é melhor do que mais tarde. Mas todo o resto não é igual quando se trata de lote versus streaming. Prefiro avaliar nossas prioridades atuais da seguinte forma:

  1. Capture a mudança
  2. Reduza os tempos de carregamento
  3. Diminuir a latência

Estou pensando em reduzir a latência de um dia para uma hora (em vez de um segundo para um milissegundo). Vamos dar uma olhada em cada um deles por vez.

Capture a mudança

Em grande medida, a análise consiste em encontrar padrões subjacentes que ajudarão você a entender o mundo. Compreender o mundo ao seu redor ajuda você a tomar decisões — espero que decisões ajudem sua empresa a crescer. Há muito a ser dito sobre como (e como não) transformar dados em insights (ou, melhor ainda, em decisões) e, felizmente, deixo esses desafios para nossos analistas e cientistas de dados. Dito isso, acho que é bastante incontroverso afirmar que o tempo é uma dimensão importante em muitos trabalhos de análise. Tempo como em: “Ontem vendemos por 5 SEK, hoje vendemos por 10 SEK, quanto venderemos amanhã?”

Jay Kreps escreveu uma postagem clássica no blog com o título “O registro: o que todo engenheiro de software deve saber sobre a abstração unificadora de dados em tempo real”, que faz um trabalho muito melhor do que eu, explicando os benefícios de capturar mudanças ao longo do tempo no formato de um registro de eventos. O ponto principal de nosso caso de uso é que nosso sistema de pagamentos geralmente armazena informações sobre o mundo como está agora e, apenas em um grau limitado, como era ontem. Ou meio segundo atrás. Seria impraticável usar um banco de dados OLTP para manter todas as alterações por longos períodos, mas se o sistema de pagamento puder simplesmente disparar eventos à medida que eles acontecem e alguém os coleta do outro lado de um agente de mensagens, eles podem ser usados para “reproduzir” e reconstruir o estado do mundo a qualquer momento que você queira estudar em retrospectiva.

Reduza os tempos de carregamento

Infelizmente, o banco de dados do nosso produto de pagamento não tem um carimbo de data e hora da “última modificação” para todas as tabelas. Isso significa que não há como saber quais das linhas em uma tabela mudaram entre ontem e hoje — ou entre um segundo atrás e agora. Para ter dados consistentes na plataforma de dados, precisamos exportar tabelas inteiras do sistema de produção todas as noites. E à medida que os volumes de transações da Trustly explodiram, o mesmo aconteceu com nossas exportações noturnas de dados. Você poderia argumentar que o banco de dados deveria ter sido projetado de uma maneira melhor para começar, mas quando o sistema foi criado há muitos anos, o foco era lançar um produto funcional que pudéssemos vender, não em adaptar-se a uma plataforma de análise que poderíamos construir vários anos no futuro (se ainda estivéssemos no mercado até então).

Obter um fluxo de eventos, ou seja, apenas coisas novas, reduz drasticamente a computação e a largura de banda gastas na atualização dos dados em nossa plataforma para o estado mais recente.

Diminuir a latência

Provavelmente é nisso que você pensa pela primeira vez quando ouve a palavra “streaming” e, claro, é algo que também importa para nós. Não se limitar a ter dados novos apenas uma vez por dia permite novos usos dos dados. O que você deve ter em mente, porém, é que o streaming é difícil. Uma comparação no mundo real pode ser a diferença entre fazer trabalhos de encanamento em suas linhas de abastecimento de água (streaming) e regar suas plantas (lote). As consequências de um erro na primeira são muito mais graves (casa inundada) do que na segunda (peitoril da janela molhado). Se você tem uma estufa, o trabalho de encanamento para instalar água pode valer a pena, mas se você tiver apenas cinco plantas em seu apartamento, convém restringir suas ambições de estar na vanguarda tecnológica. Eu diria que o mesmo pensamento vale para plataformas de dados.

Nossa solução

Com isso em mente, decidimos, há cerca de um ano, criar uma estrutura que melhoraria a ingestão de dados em nossa plataforma de dados. O trabalho ainda não está concluído (provavelmente nunca estará), mas é isso que descobrimos até agora.

Produtores -> Pub/Sub -> Beam (Dataflow) -> Google Cloud Storage -> Airflow (Cloud Composer) -> BigQuery -> dbt -> BigQuery -> Consumidores

Essa solução está em produção para alguns subcomponentes do nosso sistema de pagamento desde o final de agosto, e ainda estamos avaliando como melhorá-la. Fizemos algumas observações até agora.

Esquemas rígidos são fundamentais para dados estruturados

Escolhemos o Avro para a codificação das mensagens enviadas pelos produtores. Depois de experimentar os recursos de detecção automática de JSON puro do BigQuery no ano passado, sabíamos que precisávamos de algo mais rigoroso para não acabar com um inferno de falhas/manutenção para a equipe de dados. Junto com uma das equipes de desenvolvimento de produtos (e eventuais produtores de dados), analisamos o Protobuf e o JSON com esquemas, mas o Avro parecia ser a escolha com menos desvantagens.

Embora haja algum suporte básico para esquemas no GCP, por exemplo, você pode atribuir esquemas Avro a tópicos do Pub/Sub, nossa experiência mostra que isso é muito mais imaturo do que o que, por exemplo, o Kafka tem a oferecer. O GCP está melhorando o tempo todo, então talvez daqui a um ano as coisas pareçam diferentes. Por enquanto, temos um armazenamento de esquemas em um bucket do GCS onde os produtores colocam seus esquemas e de onde o trabalho de ingestão do Beam pode lê-los.

Use serviços em nuvem quando possível

A menos que você tenha necessidades muito específicas ou já tenha muita competência em alguma área, descobrimos que usar serviços em nuvem é uma maneira fácil de colocar algo escalável em produção no menor tempo possível. Na verdade, começamos a criar o pipeline com base no Kafka, mas depois mudamos para o Pub/Sub quando ficou claro que a equipe de serviços de dados teria que fazer uma boa parte da operação e manutenção do componente de entrega de eventos (Kafka ou Pub/Sub). Uma razão para não optar por um serviço em nuvem é o risco de bloqueio, mas se você tomar algum cuidado ao fazer a implementação, por exemplo, usar apenas a estrutura para sua finalidade principal de forma desacoplada e não começar (ab) a usá-la para todo tipo de coisa, ela deve ser substituível. Obviamente, ainda melhor é se o serviço em nuvem for baseado em uma estrutura de código aberto em que a lógica possa ser movida para a solução hospedada de outro fornecedor de nuvem, por exemplo, Airflow (Cloud Composer) ou Beam (Dataflow), caso seja necessário.

A API Python do Beam é imatura em comparação com Java

A competência da nossa equipe é principalmente em Python e SQL, então uma escolha natural para nós foi desenvolver o código Beam que faz a ingestão do Pub/Sub para o BigQuery em Python. No entanto, depois de passar um bom tempo, começamos a perceber que o uso do Java teria nos dado melhor suporte e mais opções. Para ser justo, a documentação do Beam não esconde esse fato, mas nós, talvez um pouco ingenuamente, não demos muita atenção a isso de antemão. Por exemplo, a falta de um sistema de digitação rígido do Python pode facilitar o início de algo, mas quando você quer ter certeza de que pode lidar com todas as conversões de tipo entre um esquema Avro e uma tabela do BigQuery, o Java é mais confiável.

Também acontece que as fontes e coletores Java fornecem mais funcionalidades prontas para uso, por exemplo, você pode fornecer ao conector BigQueryIO em Java um nome de tabela para gravar com base em uma função que você define para ser avaliada em tempo de execução. Para Python, o nome da tabela precisa ser baseado em um campo no evento de entrada. Resumindo: se você optar por usar o Python, terá mais restrições sobre como criar seu pipeline e alguns dos recursos que ele oferece parecem mais ou menos experimentais. Normalmente, você precisa examinar o código-fonte para descobrir o que ele realmente faz e quais limitações existem.

Considere a microdosagem para problemas em que você não precisa de tempo real

Na Trustly, temos casos de uso que exigem dados de streaming quase em tempo real para o pipeline, mas nenhum deles está totalmente implementado na plataforma ainda. Um dos motivos pelos quais escolhemos o Beam para ingestão é que ele nos permitiria combinar fluxos de streaming e em lote e, até certo ponto, alternar entre os dois. Dependendo das necessidades do consumidor de dados, podemos oferecer um “produto de dados” que não seja mais complexo do que o necessário. Em nosso caso, microlotes significa armazenar dados como arquivos Avro no GCS a cada 10 minutos. Uma vez por dia, carregamos esses arquivos em tabelas particionadas no BigQuery. Durante o dia, os dados podem ser consultados (com até 10 minutos de latência) em uma tabela externa do BigQuery apontando para a pasta no GCS onde os arquivos atuais são colocados, muito parecido com as camadas de lote e velocidade de uma arquitetura lambda.

A vantagem disso é que temos mais liberdade na forma como, eventualmente, estruturamos os dados no BigQuery. Se os dados estão constantemente sendo transmitidos para as tabelas, é difícil mudar as coisas, por exemplo, adicionar particionamento a uma tabela. (Se voltarmos à analogia do encanamento, é como tentar substituir a mangueira da máquina de lavar louça quando ela está funcionando e não há como desligar o suprimento de água). Além disso, como estamos consumindo dias inteiros em tabelas particionadas por dia, obtemos trabalhos idempotentes e, no caso de uma falha em algum lugar do pipeline, é muito mais fácil resolver as coisas e voltar a um estado conhecido.

Conclusão

Você merece algum crédito se chegou até aqui, mas acho que acabei de arranhar a superfície de (um componente de) nossa configuração de dados. Há mais coisas que eu gostaria de compartilhar. Por exemplo, nossa jornada com o Airflow/Cloud Composer e como ampliamos o uso de dbt na organização. No entanto, espero que isso tenha dado pelo menos algumas dicas sobre no que estamos trabalhando e as razões para escolher nossa solução específica. Se você acha que existem maneiras melhores de fazer isso ou se acha que essas tarefas parecem um desafio interessante, por que não se juntar a nós? Estamos constantemente procurando engenheiros de dados qualificados para aumentar a equipe e melhorar nossa prática dentro da empresa.

 

Por Isacson
Chefe de Engenharia de Dados

Fique por dentro

Obtenha informações e atualizações exclusivas sobre tudo o que diz respeito ao Open Banking e aos Pagamentos.

Fique por dentro

Obtenha informações e atualizações exclusivas sobre tudo o que diz respeito ao Open Banking e aos Pagamentos.

Obrigada! Seu envio foi recebido!
Opa! Algo deu errado ao enviar o formulário.

Páginas e recursos relevantes

Pay by Bank
Produto e engenharia
Risco
February 4, 2025
7 minutos
Pagamentos Open Banking seguros: como a Trustly usa o aprendizado de máquina para evitar fraudes
Open Banking
Companhia
April 8, 2024
3 minutos
ESPN BET e expanda Trustly os pagamentos instantâneos com o FedNow® ️
Open Banking
Produto e engenharia
January 29, 2024
8 minutos
Escalando a Inteligência Artificial (IA) no Open Banking: Construindo a plataforma de aprendizado de máquina da Trustly