Data

14 ago, 2018

Databook: transformando Big Data em conhecimento com metadados na Uber

Publicidade

De locais e destinos de motorista e passageiro a pedidos de restaurante e transações de pagamento; cada interação na plataforma de transporte da Uber é conduzida por dados. Os dados potencializam o mercado global da Uber, permitindo experiências de usuário mais confiáveis ​​e perfeitas em todos os nossos produtos para passageiros, motoristas e clientes Uber Eats em todo o mundo, bem como capacitando nossos próprios funcionários para realizar seus trabalhos com mais eficiência.

A Uber leva os dados para o próximo nível com a complexidade de seus sistemas e amplitude de dados, processando trilhões de mensagens Kafka por dia, armazenando centenas de petabytes de dados no HDFS em vários centros de dados e suportando milhões de consultas analíticas semanais.

Big data por si só, no entanto, não é suficiente para alavancar insights; para serem usados ​​de forma eficiente e eficaz, os dados na escala Uber exigem contexto para tomar decisões de negócios e obter insights. Para fornecer mais informações, criamos a plataforma interna Databook da Uber, que mostra e gerencia os metadados sobre os locais internos e os proprietários de determinados conjuntos de dados, permitindo transformar os dados em conhecimento.

Crescimento exponencial de negócios (e dados)

Desde 2016, a Uber adicionou várias novas linhas de negócios à sua plataforma, incluindo Uber Eats, Uber Freight e Jump Bikes. Agora, completamos mais de 15 milhões de viagens por dia, com mais de 75 milhões de passageiros ativos por mês. Nos últimos oito anos, a empresa cresceu de uma pequena startup para 18.000 funcionários em todo o mundo.

Com esse crescimento, surge uma complexidade cada vez maior de sistemas de dados e arquitetura de engenharia. Por exemplo, dezenas de milhares de tabelas existem nos vários mecanismos de análise que usamos, incluindo Hive, Presto e Vertica.

Essa dispersão torna imperativo ter total visibilidade de quais informações estão disponíveis, especialmente à medida em que continuamos adicionando novos dados e funcionários da linha de negócios. Em 2015, a Uber começou a catalogar suas tabelas com um conjunto de arquivos HTML estáticos que foram mantidos manualmente.

Conforme a empresa crescia, o mesmo acontecia com o número de tabelas e metadados relevantes que precisávamos atualizar. Para garantir que nossa análise de dados acompanhasse o ritmo de crescimento de nossa empresa, precisávamos de uma maneira mais fácil e rápida de fazer essas atualizações. Nesta escala, e ritmo de crescimento, ter um sistema robusto para descobrir todos os conjuntos de dados e seus metadados relevantes não é apenas agradável; é absolutamente essencial para tornar os dados úteis na Uber.

Figura 1. O Databook é a plataforma interna da Uber que cria e gerencia metadados sobre locais e proprietários de dados internos.

Para facilitar a descoberta e a exploração de conjuntos de dados, criamos o Databook. A plataforma Databook gerencia e apresenta metadados ricos sobre os conjuntos de dados da Uber, permitindo que os funcionários da Uber explorem, descubram e utilizem efetivamente os dados na Uber.

O Databook garante que o contexto sobre os dados – o que significa, sua qualidade e muito mais – não se perca entre as milhares de pessoas que tentam analisá-lo. Em suma, os metadados da Databook capacitam engenheiros, cientistas de dados e equipes de operações da Uber a passar da visualização de dados brutos para ter conhecimento acionável.

Com o Databook, passamos de fazer atualizações manuais no sentido de aproveitar um armazenamento de metadados avançado e automatizado para passar a coletar uma grande variedade de metadados atualizados com frequência. Databook incorpora os seguintes recursos:

  • Extensibilidade: novos metadados, armazenamento e entidades são fáceis de adicionar.
  • Acessibilidade: os serviços podem acessar todos os metadados programaticamente.
  • Escalabilidade: suporte para leitura de alto rendimento.
  • Potência: leitura e gravação do centro de dados cruzados.

O Databook fornece uma grande variedade de metadados derivados do Hive, Vertica, MySQL, Postgres, Cassandra e vários outros sistemas internos de armazenamento, incluindo:

  • Esquema de tabela
  • Descrições de tabela/coluna
  • Dados de amostra
  • Estatísticas
  • Linhagem
  • O frescor da tabela, os SLAs e proprietários
  • Categorização de dados pessoais

Todos os metadados são acessíveis por meio de visualizações em uma interface do usuário central e em uma API RESTful. A UI do Databook permite que os usuários acessem os metadados facilmente, enquanto a API permite que os metadados do Databook potencializem outros serviços e casos de uso em toda a Uber.

Embora já existissem soluções de código aberto como o WhereHows do LinkedIn, o framework Play e o Gradle não eram suportados na Uber durante o desenvolvimento do Databook. O WhereHows também não tinha o suporte de leitura e gravação entre centros de dados que era essencial para nossas necessidades de desempenho.

Assim, nos propusemos a criar nossa própria solução interna, escrita em Java, para alavancar sua funcionalidade integrada e seu ecossistema maduro.

Em seguida, mostraremos como criamos o Databook e os desafios que enfrentamos ao longo do caminho.

Arquitetura Databook

A arquitetura do Databook pode ser dividida em três seções: como os metadados são coletados, como os metadados são armazenados e como os metadados são revelados. A figura 2, abaixo, descreve a arquitetura geral da ferramenta:

Figura 2. A arquitetura do Databook coleta metadados do Vertica, Hive e outros sistemas de armazenamento, armazena-os em seus bancos de dados back-end e gera os dados usando APIs RESTful.

O Databook consome várias fontes como entradas, armazena os metadados relevantes e gera essas informações por meio de APIs RESTful, que potencializam a interface do usuário do Databook.

Quando projetamos o Databook pela primeira vez, uma importante decisão que tínhamos que tomar era se deveríamos armazenar os metadados que coletamos ou buscá-los conforme solicitado. Nosso serviço precisava suportar leitura de alta produtividade e baixa latência e, se delegássemos essa responsabilidade às fontes de metadados, exigiria que todas as fontes suportassem leitura de alta produtividade e baixa latência, o que introduziria complexidade e risco.

Por exemplo, uma consulta Vertica que busca o esquema da tabela normalmente demora alguns segundos para ser processada, tornando-a inadequada para visualizações. Da mesma forma, nosso metastore Hive gerencia todos os metadados do Hive, tornando arriscado exigir suporte para solicitações de leitura de alto rendimento. Como o Databook suporta tantas fontes de metadados diferentes, decidimos armazenar os metadados na própria arquitetura do Databook.

Além disso, embora a maioria dos casos de uso exija novos metadados, eles não precisam ver alterações de metadados em tempo real, tornando possível o rastreamento periódico.

Também separamos a camada de exibição de solicitação da camada de coleta de dados para que cada um seja executado em um processo separado, conforme mostrado na Figura 3, abaixo:

Figura 3. O Databook é composto por duas camadas de aplicativo diferentes: rastreadores de coleta de dados e uma camada de exibição de solicitação.

Isso isola as duas camadas, reduzindo assim o impacto colateral. Por exemplo, tarefas de rastreamento de coleta de dados podem usar recursos significativos do sistema, o que poderia afetar o SLA das APIs na camada de veiculação da solicitação.

Além disso, em comparação com a camada de veiculação de solicitação do Databook, a camada de coleta de dados é menos sensível a interrupções, garantindo que, se a camada de coleta de dados estiver inativa, os metadados desatualizados ainda serão exibidos, minimizando o impacto para os usuários.

Coleta baseada em eventos versus coleta agendada

Nosso próximo desafio foi determinar como poderíamos coletar metadados de forma mais eficiente e eficaz de várias fontes de dados diferentes e singulares. Consideramos várias opções, incluindo: criar uma framework tolerante à falhas de maneira distribuída e aproveitar o streaming baseado em eventos para detectar e depurar problemas quase em tempo real.

Primeiro, criamos rastreadores para coletar periodicamente informações de nossas várias fontes de dados e micros serviços que geram informações de metadados sobre conjuntos de dados, como estatísticas de uso de tabelas derivadas de nossa poderosa ferramenta de software livre para analisar SQL, Queryparser. (curiosidade: a Queryparser também foi construída pela nossa equipe de Plataforma de Conhecimento de Dados).

Precisávamos coletar informações de metadados frequentemente de maneira escalonável, sem bloquear outras tarefas do rastreador. Para isso, implantamos nossos rastreadores em diferentes máquinas, exigindo uma coordenação eficaz entre os rastreadores de maneira distribuída. Consideramos a configuração do Quartz no modo de clustering para o escalonamento distribuído (suportado pelo MySQL).

No entanto, enfrentamos dois bloqueadores que nos impediram de implementar essa solução: primeiro, a execução do Quartz no modo de cluster em várias máquinas exige que os relógios Quartz sejam periodicamente sincronizados, adicionando uma dependência externa e, segundo, vivenciamos a constante instabilidade da conexão MySQL após o início dos planejadores.

Como resultado, descartamos a possibilidade de executar o Quartz no modo de clustering. No entanto, ainda decidimos usar o Quartz por sua robusta funcionalidade de agendamento na memória para tornar as tarefas de publicação em nossa fila de tarefas mais fáceis e eficientes. Para a fila de tarefas do Databook, aproveitamos a framework de execução de tarefas de código aberto da Uber, a Cherami.

Essa ferramenta de software livre nos permite separar aplicativos de consumidor em um sistema distribuído, permitindo que eles se comuniquem de maneira assíncrona em vários grupos de consumidores. Com a Cherami, implantamos rastreadores em contêineres do Docker em diferentes hosts e em vários centros de dados. O uso do Cherami possibilitou a coleta de vários metadados de várias fontes diferentes, sem bloquear quaisquer tarefas, mantendo o consumo de CPU e memória sob um nível desejável e em um único host.

Embora nossos rastreadores trabalhassem para a maioria dos tipos de metadados, alguns metadados precisavam ser capturados quase em tempo real, e é por isso que decidimos fazer a transição para uma arquitetura baseada em eventos usando o Kafka. Com isso, podemos detectar e depurar as interrupções de dados instantaneamente. Nosso sistema também pode capturar alterações críticas de metadados, como a linhagem e o frescor/atualização do conjunto de dados, conforme mostrado na Figura 4 abaixo:

Figura 4. No Databook, a linhagem/atualização de metadados é coletada para cada tabela.

Essa arquitetura permite que nosso sistema acione programaticamente outros microsserviços e envie comunicações para usuários de dados quase em tempo real. No entanto, ainda usamos nossos rastreadores para tarefas como coleta (ou atualização) de dados de amostra, limitação de solicitações em recursos de destino e metadados que não necessariamente precisam ser coletados quando ocorre um evento que aciona automaticamente outros sistemas (por exemplo, estatísticas de uso do conjunto de dados).

Além de pesquisar e coletar metadados quase em tempo real, a interface de usuário do Databook também coleta informações semânticas manuais sobre conjuntos de dados de consumidores e produtores de conjuntos de dados, como descrições de tabelas e colunas.

Como nós armazenamos metadados

Na Uber, a maioria dos nossos pipelines é executada em vários clusters para propósitos de falha. Como resultado, os valores (por exemplo, latência e uso) de alguns tipos de metadados podem diferir para a mesma tabela em diferentes clusters, que são definidos como específicos do cluster.

Por outro lado, os metadados manuais coletados dos usuários são agnósticos em cluster: as descrições e as informações de propriedade se aplicam à mesma tabela nos clusters. Para vincular esses dois tipos de metadados corretamente, como associar uma descrição de coluna a uma coluna de tabela em todos os clusters, duas abordagens em potencial podem ser adotadas: link durante a gravação ou link durante a leitura.

Link durante a gravação

Ao associar metadados específicos de cluster com metadados agnósticos de cluster, a estratégia mais direta é vincular metadados durante a gravação. Por exemplo, quando um usuário adiciona uma descrição de coluna a uma determinada coluna da tabela, nós persistimos as informações na tabela em todos os clusters, mostrados na Figura 5, abaixo:

Figura 5. O Databook persiste os metadados agnósticos do cluster para todas as tabelas.

Essa abordagem garante que os dados persistentes estejam em um estado limpo. Por exemplo, na Figura 5, se a “coluna 1” não existir, ela rejeitará a solicitação. No entanto, há um grande problema: para vincular metadados agnósticos de cluster a metadados específicos de cluster durante o tempo de gravação, todos os metadados específicos de cluster devem estar presentes e há apenas uma chance em termos de tempo.

Por exemplo, quando a descrição é acionada na Figura 4, somente o Cluster 1 tem essa “coluna 1”, então a gravação no Cluster 2 falha. Posteriormente, o esquema da mesma tabela no Cluster 2 é atualizado, mas a chance escapou e essa descrição nunca estará disponível, a menos que periodicamente tentemos novamente a gravação, o que complicará o sistema. A Figura 6, abaixo, descreve este cenário:

Figura 6. O Databook persiste metadados agnósticos de cluster para todas as tabelas.

Link durante a leitura

Outra maneira de atingir o objetivo é vincular metadados agnósticos de cluster e metadados específicos de cluster durante a leitura. Essa abordagem resolve o problema da falta de metadados no link durante a gravação, pois esses dois tipos de metadados são vinculados durante a leitura, sempre que os metadados específicos do cluster estiverem presentes. Quando a “coluna 1” aparecer depois que o esquema for atualizado, sua descrição será mesclada no momento em que os usuários lerem, conforme ilustrado na Figura 7, abaixo:

Figura 7. O Databook vincula metadados específicos de cluster e metadados agnósticos de cluster durante as leituras.

Escolha de armazenamento

O MySQL foi inicialmente usado para potencializar o back-end do Databook, já que é rápido de desenvolver e pode ser provisionado automaticamente por meio do portal de infraestrutura da Uber. No entanto, quando se trata de suporte a vários centros de dados, um cluster MySQL compartilhado não é ideal por três razões:

  • Um único mestre: primeiro, apenas um único mestre era suportado na Uber, resultando em tempos de gravação lentos (adicionando ~ 70ms para cada gravação no nosso caso) de outros datacenters.
  • Promoção manual: Segundo, a promoção automática não era suportada no momento. Como resultado, se o node principal estava inativo, levava horas para promover um novo node mestre.
  • Volume de dados: Outra razão pela qual trocamos o MySQL é o grande volume de dados que a Uber gera. Pretendíamos manter todas as alterações no histórico e queríamos que nosso sistema suportasse futuras expansões sem gastar muito tempo na manutenção do cluster.

Por esses motivos, escolhemos o Cassandra para substituir o MySQL por causa de seu suporte de replicação XDC robusto, o que nos permite gravar dados de vários centros de dados sem sofrer aumento de latência. E como o Cassandra é escalonável linearmente, não precisávamos mais nos preocupar em acomodar o crescente volume de dados da Uber.

Como nós superficializamos os dados

O Databook fornece dois meios principais de acessar metadados: uma API RESTful e uma interface de usuário visual. A API RESTful da Databook é potencializada pelo Dropwizard, um framework Java para serviços Web RESTful de alto desempenho, e é implementada em várias máquinas e carregada com balanceamento pelo serviço interno de encaminhamento de solicitações da Uber.

Na Uber, o Databook é usado principalmente por outros serviços que acessam dados de forma programática. Por exemplo, nosso serviço interno de análise/reescrita de consulta depende das informações do esquema da tabela no Databook. A API pode suportar leitura de alto rendimento e é escalonável horizontalmente, com um pico atual de consultas por segundo de cerca de 1.500.

A UI de visualização é escrita em React.js e Redux, bem como D3.js e é usada principalmente por engenheiros, cientistas de dados, analistas de dados e equipes de operações da empresa para triagem de problemas de qualidade de dados e identificação e exploração de conjuntos de dados relevantes.

Pesquisa

A pesquisa, um recurso essencial da interface de usuário do Databook, permite que os usuários acessem e naveguem facilmente os metadados da tabela. Usamos o Elasticsearch como nosso mecanismo de pesquisa de índice completo, que, por sua vez, sincroniza dados do Cassandra.

Com o Databook, os usuários podem pesquisar em várias dimensões, como nome, proprietário, coluna e coluna aninhada, descritas na Figura 8, abaixo, permitindo uma análise de dados mais atualizada e precisa:

Figura 8. O Databook permite que os usuários pesquisem por diferentes dimensões, incluindo nome, proprietário e coluna.

Próximo capítulo do Databook

Com o Databook, os metadados na Uber agora são mais práticos e úteis do que nunca, mas ainda estamos trabalhando para expandir nosso impacto, criando novas funcionalidades mais robustas. Algumas funcionalidades que esperamos desenvolver para o Databook incluem a capacidade de gerar percepções de dados com modelos de aprendizado de máquina e criar mecanismos avançados de detecção, prevenção e mitigação de problemas.

Se você está criando serviços escalonáveis e inteligentes e desenvolvendo tecnologias complexas e inovadoras com uma combinação de soluções internas e de código aberto, entre em contato com Zoe Abrams (za@uber.com) ou candidate-se para ser um de nossos funcionários!

***

Este artigo é do Uber Engineering. Ele foi escrito por Luyao Li, Kaan Onuk e Lauren Tinda. A tradução foi feita pela Redação iMasters com autorização. Você pode conferir o original em: https://eng.uber.com/databook/