Como escolhemos o novo serviço de banco de dados para as features de análise do RD Station

Kelvin Oenning
Mar 16 · 12 min read
Features de análise

Utilizar um sistema líder no setor de marketing digital como o RD Station é ótimo, mas nada melhor do que ver nossos clientes felizes ao acessar nossas features de análise e comprovar que utilizar nosso sistema está trazendo resultados magníficos para sua empresa.

Nós do Mushin somos um time especializado e 100% focado em analytics aqui na RD, estamos constantemente trabalhando, estudando e aplicando conhecimento para gerar não só as melhores features de análise dentro do RD Station como também estamos preocupados em encontrar formas de melhorar e deixar tudo mais performático e flexível para poder disponibilizar dados com mais velocidade e ainda mais detalhamentos.

Em 2019 com o crescimento da nossa base de clientes o time decidiu que seria necessário migrar uma das atuais soluções de banco de dados que englobam as features de análise, sendo ela especificamente a solução de banco da feature de ROI de Automação que utiliza o Google BigQuery.

Qual o motivo da migração?

Inicialmente a feature de ROI de Automação foi desenvolvida utilizando o Google BigQuery com a visão de que estávamos lidando com uma quantidade massiva de dados em formato temporal e que nossas queries iriam demandar muito processamento, duas coisas que apontavam o Google BigQuery como uma ótima solução.

No atual contexto o Google BigQuery se mostrou espetacular, suportando um nível gigantesco de queries que chegavam até 5 anos de análise, porém, como o objetivo do nosso time é performar e trazer sempre coisas novas para dar ao cliente o momento UAAAU, nós precisávamos de algo com menor latência e que continuasse atendendo os milhares de eventos processados todos os dias.

Em alguns casos nossas queries mais pesadas chegavam a uma latência de até 20 segundos e como o foco é trazer cada vez mais formatos de análise com mais dados para nossos clientes, nosso time percebeu que precisávamos de algo diferente.

Qual banco escolher?

Dois bancos de dados sendo eles Google BigTable e Google Spanner

Dentre muitos formatos e possibilidades, dois bancos se mostraram ser mais acolhedores para o atual contexto que queríamos chegar, sendo eles o Google BigTable e o Google Spanner.

Ambos os bancos não trabalham no estilo on-demand onde o custo operacional é calculado somente na quantidade de dados processados como é o caso do Google BigQuery, contudo, eles visam escalabilidade e baixa latência que é o esperado pelo nosso time.

Modelagem

Em cada um dos casos precisamos encontrar o modelo de dados mais adequado para nosso processo, porém, cada um dos bancos possui suas peculiaridades e precisam ter um modelo diferente.

Cada banco foi testado com cargas temporais e tamanhos que simulavam uma base quatro vezes maior que a nossa atual plataforma, para assim eleger um modelo para os testes deste documento.

Para a proposta do teste com o BigTable elaboramos e testamos alguns modelos de dados otimizado para Time Series tomando o devido cuidado para a distribuição dos dados entre os nós do cluster visto que os dados são distribuídos lexicograficamente.

Para a proposta do teste com o Spanner podemos seguir uma linha mais próxima do atual banco BigQuery onde apenas testamos vários schemas para gerar assim um modelo mais eficiente.

Agora precisamos validar, mas como vamos testar os limites desta solução?

Dentre muitos contextos e features dentro do sistema, sabemos que é com as features de análise que o cliente comprova se o dinheiro e tempo que foi investido está mesmo dando um retorno positivo, então precisamos ter algo super preciso e escalável.

Bases de dados e suas cargas

Para simplificar este post, vamos então abordar somente os testes iniciais, onde decidimos então montar uma instância mínima de cada um dos bancos onde cada carga de dados de cada banco foi feita usando um serviço de Pipelines Apache Beam chamado Google Dataflow.

Em uma visão simplista, cada base de dados recebeu um total de 350 milhões de eventos para simular a primeira bateria de testes.

“Nesta etapa, o Google Dataflow ajudou bastante pois além de já existir projetos open-source para importar dados do Google Storage para o Google BigTable, também temos um template pronto no console do Google Dataflow onde podemos importar dados do Google Storage para o Google Spanner sem muitos esforços.”

Os dados enviados para o banco foram eventos automaticamente gerados usando um modo temporal onde um script criou eventos que ocorreram entre o ano de 2010 ao ano de 2019 em alguns intervalos randômicos, possibilitando assim o teste real de queries como ocorrem em produção.

Sabemos que existe uma diferença grande entre uma instância mínima de cada um dos bancos, onde o BigTable pode trabalhar em produção com um mínimo de 3 nós no cluster, já o Spanner pode trabalhar com um mínimo de 1 nó no seu cluster.

Como o objetivo é validar cada uma das soluções e não comparar a velocidade dos bancos, não vamos levar isso em consideração e os testes vão servir para gerar uma visão de como cada serviço vai nos ajudar, levando em consideração sua escalabilidade, latência, custo e flexibilidade de uso.

Execução dos testes

Como teste inicial decidimos então utilizar uma quantidade de requisições razoável onde disparamos 4 mil requisições sequenciais para o primeiro teste e 4 mil requisições paralelas para o segundo teste, gerando assim uma visão de operação primária, onde a partir dela é gerado novos testes.

Mesmo requisições sequenciais sendo fácil de se disparar de uma só máquina, temos o problema do nível de requisições estarem influenciando o dado final do teste, e isso fica extremamente evidente quando falamos de requisições em paralelo não?

Temos várias formas de executar este tipo de processo em paralelo, porém uma forma muito simples e de fácil implantação é o uso do Serverless Framework e do Google Cloud Function, onde podemos de forma rápida implantar um projeto serverless de alta escalabilidade, podendo simular então nossas requisições tanto em sequência quanto em paralelo.

Para um teste mais real das requisições em sequência executamos com um script em Go, que realizou 4 mil chamadas diretas para uma Google Cloud Function que fez o sorteio de uma query, executou no BigTable e calculou o tempo de resposta, o mesmo sendo feito para o Spanner.

Demonstrativo da estrutura montada para emissão de requests sequenciais

No caso dos testes em paralelo este modelo precisa ser um pouco melhorado pois o tempo que estamos disparando as requisições influencia no tempo que os bancos estão recebendo cada uma, no caso elas vão ser recebidas pelos bancos em um espaço de tempo muito grande, não dando uma visão de impacto com requisições em larga escala sendo disparadas por um sistema.

Sendo assim fizemos um upgrade do modelo em execução para adicionar uma trigger de data/hora, onde agora temos no código em Go realizando somente uma chamada para uma Google Cloud Function que fica encarregada de criar uma trigger da data/hora da atual requisição adicionando 2 minutos e disparando as 4 mil requisições para outras Google Cloud Function que ficam encarregadas de esperar a data/hora estipulada para executar o disparo.

Demonstrativo da estrutura montada para emissão de requests em paralelo

Com este modelo estamos enxugando o tempo de chamada e fazendo cada Cloud Function executar sua chamada no mesmo minuto/segundo das outras, e mesmo sabendo que podem existir algumas diferenças mínimas, estamos assim executando uma simulação de requisições em paralelo de fácil implementação, onde no atual contexto inicial do teste não precisamos validar sincronização, podendo somente verificar os tempos de execução e o timestamp do disparo que já mostra se algo fugiu do controle em termos de sincronização.

Resultados do teste

Os resultados foram contabilizados e adicionados separadamente em duas tabelas, onde uma se refere aos disparos de requests sequenciais e a outra para os disparos de requests em paralelo.

Os testes de requisições em paralelo foram executados com intuito de ter uma visão de stress final de cada cluster, podendo gerar assim um alerta do que pode acontecer de crítico em uso de um cluster em sua potência total, porém, na ausência de algo crítico vamos desconsiderar os dados pois em caso de um cluster chegar ao seu limite de uso, o mesmo receberia um upgrade para trabalhar mais folgado.

Tabelas com resultados do BigTable

Se olharmos para os resultados do BigTable podemos ver que sua latência se mantém mesmo em cargas de trabalhos estressantes, isto é ocasionado pois os dados são distribuídos entre 3 nós que ficam encarregados de particionar a busca gerando mais performance.

Tabela com resultados das 4mil requests sequenciais emitidas para o BigTable
Tabela com resultados das 4mil requests paralelas emitidas para o BigTable

Tabelas com resultados do Spanner

Quando analisamos os resultados do Spanner podemos ver que com apenas um nó ele entrega um excelente resultado em queries que são disparadas sequencialmente, porém quando trabalhamos em paralelo o mesmo começa a precisar de mais tempo para processar tantas requisições.

Neste caso não é que temos uma latência ruim pois a requisição não está sendo particionada em 3 nós como ocorre com o Bigtable, e no caso do Spanner 1 nó precisa fazer todo o trabalho sozinho.

Tabela com resultados das 4mil requests sequenciais emitidas para o Spanner
Tabela com resultados das 4mil requests paralelas emitidas para o Spanner

Custo base de cada banco

Dentre a escolha dos bancos precisamos também entender quanto cada banco irá nos custar, podendo assim ter uma visão melhor nos resultados finais.

Em uma visão de nível mais básico de cada banco, podemos ver que ambos os bancos trabalham com custos bem diferentes do que o BigQuery, onde o custo é baseado em nós de uso por hora e não por demanda.

Para o levantamento de cada banco, não vamos levar em consideração custos relacionados a tráfego de dados nem o custo de storage.

Ambos os bancos possuem uma visão de trabalho em produção diferentes, onde para um cluster do BigTable precisamos ter no mínimo 3 nós rodando por hora e para o Spanner podemos ter um cluster rodando com 1 nó por hora.

Tabela de custo base do Google BigTable e Google Spanner

Essa diferença influencia um pouco no custo de operação final, e precisa ser levada em consideração quando estamos efetuando este tipo de modificações.

Escolha do banco

Levando em consideração os dados, nosso time precisou pesar os resultados em alguns pontos específicos, sendo eles:

  1. Escalabilidade;
  2. Performance;
  3. Flexibilidade;
  4. Custo;

Não podemos só escolher o que é mais rápido e pedir aprovação para nosso centro de engenharia, precisamos entender qual é a melhor opção para atender a necessidade do nosso time de análise e de outros times.

Olhando por esta visão, nosso time resolveu que o Spanner era o mais indicado pelos seguintes motivos:

  1. Escalabilidade: O ponto mais forte da escolha, pois precisamos garantir que nossas features trabalhem sem causar problemas na ocorrência de picos.
  2. Performance: Mesmo o Spanner não sendo o vencedor dos testes o mesmo já garante um tempo de resposta abaixo dos 500 ms, e pode ter seu tempo em picos melhorado com a adição de mais nós no cluster.
  3. Flexibilidade: Execução de queries por SQL.
  4. Custo: O baixo custo de um cluster rodando com apenas1 no Spanner acaba agradando pois podemos distribuir melhor nosso modelo de clusters e ter a flexibilidade de determinar melhor a quantidade de nós para cada caso.

Teste de degradação do Spanner

Chegamos em um dos pontos mais interessantes onde mesmo o time definindo qual o banco seria utilizado, precisamos então fazer um teste de degradação mais apurado, e entender em cima deste cluster o que aconteceria em casos extremos.

Um teste de degradação foi executado para poder ter uma visão mais aprofundada do que aconteceria se a escala de 4 mil requests sequenciais fosse ultrapassada.

Podemos ver no gráfico abaixo que enquanto estamos abaixo das 4 mil requests seuenciais realmente chegamos próximos aos 500 ms de resposta, porém, elevando um pouco mais a quantidade de requests que estão sendo disparadas podemos ver que o Spanner se comporta de uma melhor forma.

Gráfico de degradação utilizando o Google Spanner

Podemos entender que quando disparamos as requests em paralelo simulando vários clientes acessando a mesma feature ao mesmo tempo e a quantidade de nós que temos acaba não suportando muito bem, porém quando começamos a simular um ambiente normal de requests que ocorrem várias e várias vezes por minuto, sendo elas algumas ao mesmo tempo e algumas não, podemos ver que o cluster do Spanner passa a organizar o trabalho melhor e diminuir assim seu tempo de processamento.

Vale lembrar também que este é um ambiente simulado e na vida real podemos ter variações nesses resultados visto que os eventos podem ser diferentes, podendo estar em um ponto temporal maior ou menor, interferindo no resultado final.

Resultados após implantação do projeto

Por fim, abaixo temos alguns dos nossos dados do Datadog onde capturamos o tempo de algumas requests das features rodando com o Google BigQuery e agora com o Google Spanner.

Podemos notar que enquanto estavamos com o BigQuery, nós tínhamos a maioria das requests sendo executadas entre >2s e <5s, agora temos com o Google Spanner a maior parte sendo executada com seu tempo de resposta <250ms.

Com este upgrade de velocidade, também foi possível reduzir o número de ocorrência de timeouts, onde mesmo que nosso usuários não notassem estas ocorrências por questão das nossas políticas de retry, a demora para a chegada da informação era perceptível.

Vale lembrar que isso não desmerece o BigQuery pois o mesmo foi feito para trabalhar em ocasiões diferentes e possui várias funcionalidades que o Spanner não possui. A troca do nosso banco de dados foi realizada apenas para trazer desempenho para nossos usuários e ainda continuamos utilizando o BigQuery como nosso Data Warehouse.

BigQuery

Dados de latência utilizando o Google BigQuery — Exportados pelo Datadog

Spanner

Dados de latência utilizando o Google Spanner — Exportados pelo Datadog

Considerações finais

Para chegarmos nesses resultados e escolhermos um novo banco de dados que atenda às nossas necessidades foram alguns dias de discussão e dojos dentro do próprio time, reuniões com a equipe de Data da RD e algumas vezes com a equipe do Google.

Fizemos algumas propostas que englobam uma nova modelagem de dados e estudos de outras alternativas de banco de dados, alguns que até não estão disponíveis na GCP. E ao longo dos estudos decidimos seguir com os testes em cima do Google Spanner e Google BigTable.

Nossa intenção e necessidade eram baixar a latência nas requisições feitas inicialmente com o BigQuery, aumentando a performance e mantendo a escalabilidade e flexibilidade que ele nos oferecia.

Após todos os testes e seguindo nossos critérios, fizemos a escolha do Google Spanner como nova fonte de dados, porém, não quer dizer que iremos seguir com ele para todas as perguntas que precisam ser feitas dentro de analytics e BI da RD.

Partimos então para um planejamento de uma bifurcação no pipeline que até então só colocava dados no BigQuery para também inserirmos dados no Spanner e fazermos essa virada aos poucos com um rollout controlado.

Criamos um dashboard dentro do Datadog desde a implementação do BigQuery para acompanharmos a latência das requisições, e ao virarmos o acesso ao Spanner para algumas contas, fomos surpreendidos com a melhora na usabilidade da nossa feature.

Ao final de todas as implementações e os primeiros rollouts em contas internas, passamos mais algum tempo testando e refinando os últimos detalhes até viramos o Spanner para todas as contas de clientes da RD.

Todo esse trabalho já rendeu alguns frutos desde sua entrega no final de 2019, até então fazíamos uma busca para um caso de um fluxo de automação por vez, e agora já temos requisições de múltiplos fluxos possibilitando mostrar estatísticas de ROI na listagem de fluxos de automação e até fazer comparativos com períodos anteriores, e não notamos nenhuma degradação e nem alteração na latência.

O que no passado estava nos dando muita dor de cabeça hoje nos deu novas possibilidades para os clientes.


Este texto foi escrito de forma colaborativa pelo time Mushin

Kelvin Oenning — Software Engineer (Linkedin | Github)
Michel Azevedo — Software Engineer (Linkedin | Github)
Sergio Fiorotti — Software Engineer (Linkedin | Github)
Matheus Teixeira — Software Engineer (Linkedin | Github)

Ship It!

Conteúdo, opinião, vivência e compartilhamento de ideias da equipe de Produto e Engenharia da Resultados Digitais @RD

Kelvin Oenning

Written by

Software Engineer at Resultados Digitais

Ship It!

Ship It!

Conteúdo, opinião, vivência e compartilhamento de ideias da equipe de Produto e Engenharia da Resultados Digitais @RD

More From Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade