Arquitetura e capacidades do Tarantool Data Grid

Arquitetura e capacidades do Tarantool Data Grid

Em 2017, ganhámos um concurso para desenvolver o núcleo transacional do negócio de investimento do Alfa-Bank e começámos a trabalhar (no HighLoad++ 2018 com um relatório sobre o núcleo do negócio de investimento realizado Vladimir Drynkin, chefe do núcleo transacional do negócio de investimentos do Alfa Bank). Este sistema deveria agregar dados de transações de diferentes fontes em vários formatos, reunir os dados em um formato unificado, armazená-los e fornecer acesso a eles.

Durante o processo de desenvolvimento, o sistema evoluiu e adquiriu funcionalidades, e em algum momento percebemos que estávamos cristalizando algo muito mais do que apenas um software aplicativo criado para resolver uma gama estritamente definida de tarefas: conseguimos sistema para construção de aplicativos distribuídos com armazenamento persistente. A experiência que adquirimos formou a base de um novo produto - Grade de dados Tarantool (TDG).

Quero falar sobre a arquitetura TDG e as soluções que encontramos durante o processo de desenvolvimento, apresentar as principais funcionalidades e mostrar como nosso produto pode se tornar a base para a construção de soluções completas.

Arquitetonicamente, dividimos o sistema em papéis, cada um dos quais é responsável por resolver uma determinada gama de problemas. Uma única instância de aplicativo em execução implementa um ou mais tipos de função. Pode haver diversas funções do mesmo tipo em um cluster:

Arquitetura e capacidades do Tarantool Data Grid

Connector

O Connector é responsável pela comunicação com o mundo exterior; sua tarefa é aceitar a solicitação, analisá-la e, se for bem-sucedida, enviar os dados para processamento ao processador de entrada. Suportamos os formatos HTTP, SOAP, Kafka, FIX. A arquitetura permite simplesmente incluir suporte para novos formatos, com suporte para IBM MQ disponível em breve. Se a análise da solicitação falhar, o conector retornará um erro; caso contrário, responderá que a solicitação foi processada com sucesso, mesmo que tenha ocorrido um erro durante o processamento posterior. Isso foi feito especificamente para trabalhar com sistemas que não sabem repetir solicitações - ou, pelo contrário, fazem isso com muita persistência. Para não perder dados, é utilizada uma fila de reparo: o objeto primeiro entra nela e somente após o processamento bem-sucedido é removido dele. O administrador pode receber alertas sobre objetos restantes na fila de reparo e, após eliminar um erro de software ou falha de hardware, tentar novamente.

Processador de entrada

O processador de entrada classifica os dados recebidos de acordo com recursos característicos e chama os processadores apropriados. Manipuladores são códigos Lua executados em uma sandbox, portanto, não podem afetar o funcionamento do sistema. Nesta fase, os dados podem ser reduzidos à forma exigida e, se necessário, pode ser lançado um número arbitrário de tarefas que possam implementar a lógica necessária. Por exemplo, no produto MDM (Master Data Management) construído no Tarantool Data Grid, ao adicionar um novo usuário, para não retardar o processamento da solicitação, lançamos a criação de um golden record como uma tarefa separada. O sandbox suporta solicitações de leitura, alteração e adição de dados, permite executar alguma função em todas as funções do tipo de armazenamento e agregação do resultado (mapear/reduzir).

Os manipuladores podem ser descritos em arquivos:

sum.lua

local x, y = unpack(...)
return x + y

E então, declarado na configuração:

functions:
  sum: { __file: sum.lua }

Por que Lua? Lua é uma linguagem muito simples. Com base em nossa experiência, algumas horas depois de conhecê-lo, as pessoas começam a escrever códigos que resolvem seus problemas. E estes não são apenas desenvolvedores profissionais, mas, por exemplo, analistas. Além disso, graças ao compilador jit, Lua roda muito rapidamente.

Armazenamento

O armazenamento armazena dados persistentes. Antes de salvar, os dados são validados em relação ao esquema de dados. Para descrever o circuito usamos um formato estendido Apache Avro. Exemplo:

{
    "name": "User",
    "type": "record",
    "logicalType": "Aggregate",
    "fields": [ 
        { "name": "id", "type": "string"}, 
        {"name": "first_name", "type": "string"}, 
        {"name": "last_name", "type": "string"} 
    ], 
    "indexes": ["id"] 
}

Com base nesta descrição, DDL (Data Definition Language) é gerado automaticamente para o Tarantula DBMS e GraphQL esquema para acesso aos dados.

A replicação de dados assíncrona é suportada (há planos para adicionar uma síncrona).

Processador de saída

Às vezes é necessário avisar consumidores externos sobre a chegada de novos dados; para isso existe a função de processador de saída. Depois de salvar os dados, eles podem ser passados ​​​​para o manipulador correspondente (por exemplo, para trazê-los para o formulário exigido pelo consumidor) - e depois passados ​​​​para o conector para envio. Uma fila de reparo também é usada aqui: se ninguém aceitar o objeto, o administrador poderá tentar novamente mais tarde.

Escala

As funções de conector, processador de entrada e processador de saída não têm estado, o que nos permite dimensionar o sistema horizontalmente simplesmente adicionando novas instâncias de aplicativo com o tipo de função desejado habilitado. O armazenamento é usado para dimensionamento horizontal abordagem para organizar um cluster usando buckets virtuais. Depois de adicionar um novo servidor, alguns dos buckets dos servidores antigos são movidos para o novo servidor em segundo plano; isso acontece de forma transparente para os usuários e não afeta o funcionamento de todo o sistema.

Propriedades de dados

Os objetos podem ser muito grandes e conter outros objetos. Garantimos a atomicidade de adição e atualização de dados armazenando um objeto com todas as dependências em um bucket virtual. Isso evita que o objeto fique “espalhado” por vários servidores físicos.

O versionamento é suportado: cada atualização de um objeto cria uma nova versão, e sempre podemos analisar um intervalo de tempo e ver como era o mundo naquela época. Para dados que não necessitam de um histórico longo, podemos limitar o número de versões ou até mesmo armazenar apenas uma – a mais recente – ou seja, essencialmente desabilitar o versionamento para um determinado tipo. Você também pode limitar o histórico por tempo: por exemplo, exclua todos os objetos de um determinado tipo com mais de 1 ano. O arquivamento também é suportado: podemos descarregar objetos mais antigos que o tempo especificado, liberando espaço no cluster.

Tarefas

Entre as funcionalidades interessantes, vale destacar a possibilidade de iniciar tarefas de forma agendada, a pedido do usuário ou programaticamente a partir do sandbox:

Arquitetura e capacidades do Tarantool Data Grid

Aqui vemos outro papel - corredor. Essa função não tem estado e instâncias de aplicativos adicionais com essa função podem ser adicionadas ao cluster conforme necessário. A responsabilidade do corredor é completar as tarefas. Conforme mencionado, é possível gerar novas tarefas a partir do sandbox; eles são salvos em uma fila de armazenamento e depois executados no executor. Este tipo de tarefa é chamado de Job. Também temos um tipo de tarefa chamado Task - são tarefas definidas pelo usuário que são executadas de acordo com um agendamento (usando a sintaxe cron) ou sob demanda. Para iniciar e rastrear essas tarefas, temos um gerenciador de tarefas conveniente. Para que esta funcionalidade esteja disponível, você deve habilitar a função de agendador; essa função tem um estado, portanto não é escalável, o que não é obrigatório; ao mesmo tempo, como todas as outras funções, pode ter uma réplica que começa a funcionar se o mestre recusar repentinamente.

Logger

Outra função é chamada de logger. Ele coleta logs de todos os membros do cluster e fornece uma interface para carregá-los e visualizá-los por meio da interface da web.

Serviços

Vale ressaltar que o sistema facilita a criação de serviços. No arquivo de configuração, você pode especificar quais solicitações serão enviadas para um manipulador escrito pelo usuário que é executado na sandbox. Neste manipulador você pode, por exemplo, executar algum tipo de consulta analítica e retornar o resultado.

O serviço está descrito no arquivo de configuração:

services:
   sum:
      doc: "adds two numbers"
      function: sum
      return_type: int
      args:
         x: int
         y: int

A API GraphQL é gerada automaticamente e o serviço fica disponível para chamada:

query {
   sum(x: 1, y: 2) 
}

Isso chamará o manipulador sumque retornará o resultado:

3

Perfil e métricas de consulta

Para entender o funcionamento do sistema e as solicitações de perfil, implementamos suporte para o protocolo OpenTracing. O sistema pode enviar informações sob demanda para ferramentas que suportam este protocolo, como o Zipkin, o que permitirá entender como a solicitação foi executada:

Arquitetura e capacidades do Tarantool Data Grid

Naturalmente, o sistema fornece métricas internas que podem ser coletadas usando Prometheus e visualizadas usando Grafana.

Implantar

O Tarantool Data Grid pode ser implantado a partir de pacotes RPM ou de um arquivo, usando um utilitário da distribuição ou Ansible, também há suporte para Kubernetes (Operador Tarantool Kubernetes).

O aplicativo que implementa a lógica de negócios (configuração, manipuladores) é carregado no cluster Tarantool Data Grid implantado na forma de um arquivo por meio da UI ou usando um script por meio da API fornecida por nós.

Exemplos de aplicativos

Quais aplicativos podem ser criados usando Tarantool Data Grid? Na verdade, a maioria das tarefas de negócios está de alguma forma relacionada ao processamento, armazenamento e acesso ao fluxo de dados. Portanto, se você tiver grandes fluxos de dados que precisam ser armazenados e acessados ​​com segurança, nosso produto poderá economizar muito tempo de desenvolvimento e focar em sua lógica de negócios.

Por exemplo, queremos recolher informação sobre o mercado imobiliário, para que no futuro, por exemplo, tenhamos informação sobre as melhores ofertas. Neste caso, destacaremos as seguintes tarefas:

  1. Robôs que coletam informações de fontes abertas serão nossas fontes de dados. Você pode resolver esse problema usando soluções prontas ou escrevendo código em qualquer linguagem.
  2. Em seguida, o Tarantool Data Grid aceitará e salvará os dados. Se o formato dos dados de diferentes fontes for diferente, então você pode escrever um código em Lua que realizará a conversão para um único formato. Na fase de pré-processamento, você também poderá, por exemplo, filtrar ofertas duplicadas ou atualizar adicionalmente na base de dados informações sobre agentes que atuam no mercado.
  3. Agora você já tem uma solução escalável em um cluster que pode ser preenchido com dados e fazer seleções de dados. Então você pode implementar novas funcionalidades, por exemplo, escrever um serviço que fará uma solicitação de dados e dará a oferta mais vantajosa por dia - isso exigirá algumas linhas no arquivo de configuração e um pouco de código Lua.

Qual é o próximo?

Nossa prioridade é melhorar a facilidade de desenvolvimento usando Grade de dados Tarantool. Por exemplo, este é um IDE com suporte para criação de perfil e depuração de manipuladores em execução em uma sandbox.

Também prestamos muita atenção às questões de segurança. No momento, estamos passando pela certificação do FSTEC da Rússia para confirmar o alto nível de segurança e atender aos requisitos de certificação de produtos de software usados ​​em sistemas de informação de dados pessoais e sistemas de informação governamentais.

Fonte: habr.com

Adicionar um comentário