Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Olá, meu nome é Eugene. Trabalho na infraestrutura de pesquisa Yandex.Market. Quero contar à comunidade Habr sobre a cozinha interna do Mercado - e tenho muito para contar. Em primeiro lugar, como funciona a busca de mercado, processos e arquitetura. Como lidamos com situações de emergência: o que acontece se um servidor cair? E se houver 100 desses servidores?

Você também aprenderá como implementamos novas funcionalidades em vários servidores ao mesmo tempo. E como testamos serviços complexos diretamente na produção, sem causar nenhum transtorno aos usuários. De maneira geral, como funciona a busca do Mercado para que todos se divirtam.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Um pouco sobre nós: que problema resolvemos

Ao inserir texto, pesquisar um produto por parâmetros ou comparar preços em diferentes lojas, todas as solicitações são enviadas para o serviço de pesquisa. A pesquisa é o maior serviço do mercado.

Processamos todas as solicitações de pesquisa: dos sites market.yandex.ru, beru.ru, serviço Supercheck, Yandex.Advisor, aplicativos móveis. Também incluímos ofertas de produtos nos resultados de pesquisa em yandex.ru.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Por serviço de pesquisa entendo não só a pesquisa em si, mas também uma base de dados com todas as ofertas do Mercado. A escala é esta: mais de um bilhão de solicitações de pesquisa são processadas por dia. E tudo deve funcionar de forma rápida, sem interrupções e sempre produzir o resultado desejado.

O que é o quê: Arquitetura de mercado

Descreverei brevemente a arquitetura atual do Mercado. Pode ser descrito aproximadamente pelo diagrama abaixo:
Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar
Digamos que uma loja parceira venha até nós. Ele diz que quero vender um brinquedo: esse gato malvado com um guincho. E outro gato bravo sem guinchar. E apenas um gato. Depois a loja precisa preparar as ofertas que o Mercado busca. A loja gera um xml especial com ofertas e comunica o caminho para esse xml através da interface do afiliado. O indexador então baixa periodicamente esse xml, verifica se há erros e salva todas as informações em um enorme banco de dados.

Existem muitos desses xmls salvos. Um índice de pesquisa é criado a partir deste banco de dados. O índice é armazenado em formato interno. Depois de criar o índice, o serviço Layout o carrega nos servidores de pesquisa.

Como resultado, um gato zangado com um guincho aparece no banco de dados e o índice do gato aparece no servidor.

Vou lhe contar como procuramos um gato na parte sobre arquitetura de pesquisa.

Arquitetura de pesquisa de mercado

Vivemos em um mundo de microsserviços: cada solicitação recebida mercado.yandex.ru causa muitas subconsultas e dezenas de serviços estão envolvidos em seu processamento. O diagrama mostra apenas alguns:

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar
Esquema simplificado de processamento de solicitações

Cada serviço tem uma coisa maravilhosa - seu próprio balanceador com um nome exclusivo:

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

O balanceador nos dá maior flexibilidade no gerenciamento do serviço: você pode, por exemplo, desligar servidores, o que muitas vezes é necessário para atualizações. O balanceador percebe que o servidor está indisponível e redireciona automaticamente as solicitações para outros servidores ou data centers. Ao adicionar ou remover um servidor, a carga é automaticamente redistribuída entre os servidores.

O nome exclusivo do balanceador não depende do data center. Quando o serviço A faz uma solicitação a B, por padrão, o balanceador B redireciona a solicitação para o data center atual. Se o serviço estiver indisponível ou não existir no data center atual, a solicitação será redirecionada para outros data centers.

Um único FQDN para todos os data centers permite que o serviço A abstraia completamente os locais. Sua solicitação ao serviço B sempre será processada. A exceção é quando o serviço está localizado em todos os data centers.

Mas nem tudo é tão bom com este balanceador: temos um componente intermediário adicional. O balanceador pode estar instável e esse problema é resolvido por servidores redundantes. Existe também um atraso adicional entre os serviços A e B. Mas na prática é inferior a 1 ms e para a maioria dos serviços isto não é crítico.

Lidando com o inesperado: equilíbrio e resiliência do serviço de pesquisa

Imagine que há um colapso: você precisa encontrar um gato com um chiado, mas o servidor trava. Ou 100 servidores. Como sair? Vamos mesmo deixar o usuário sem gato?

A situação é assustadora, mas estamos preparados para isso. Eu vou te contar em ordem.

A infraestrutura de pesquisa está localizada em vários data centers:

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Ao projetar, incluímos a possibilidade de desligar um data center. A vida é cheia de surpresas - por exemplo, uma escavadeira pode cortar um cabo subterrâneo (sim, isso aconteceu). A capacidade nos restantes data centers deverá ser suficiente para suportar picos de carga.

Vamos considerar um único data center. Cada data center possui o mesmo esquema de operação do balanceador:

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar
Um balanceador consiste em pelo menos três servidores físicos. Essa redundância é feita para oferecer confiabilidade. Os balanceadores são executados em HAProx.

Escolhemos o HAProx devido ao seu alto desempenho, baixos requisitos de recursos e ampla funcionalidade. Nosso software de busca é executado dentro de cada servidor.

A probabilidade de um servidor falhar é baixa. Mas se você tiver muitos servidores, a probabilidade de pelo menos um cair aumenta.

Isto é o que acontece na realidade: os servidores travam. Portanto, é necessário monitorar constantemente o estado de todos os servidores. Se o servidor parar de responder, ele será automaticamente desconectado do tráfego. Para isso, o HAProxy possui uma verificação de integridade integrada. Ele vai para todos os servidores uma vez por segundo com uma solicitação HTTP “/ping”.

Outro recurso do HAProxy: a verificação de agente permite carregar todos os servidores uniformemente. Para isso, o HAProxy se conecta a todos os servidores, e eles retornam seu peso dependendo da carga atual de 1 a 100. O peso é calculado com base no número de solicitações na fila de processamento e na carga do processador.

Agora, sobre como encontrar o gato. A pesquisa resulta em solicitações como: /search?text=bravo+gato. Para que a pesquisa seja rápida, todo o índice cat deve caber na RAM. Mesmo a leitura do SSD não é rápida o suficiente.

Antigamente o banco de dados de ofertas era pequeno e a RAM de um servidor bastava para isso. À medida que a base de ofertas cresceu, tudo não cabia mais nesta RAM e os dados foram divididos em duas partes: fragmento 1 e fragmento 2.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar
Mas isto acontece sempre: qualquer solução, mesmo que boa, dá origem a outros problemas.

O balanceador ainda foi para qualquer servidor. Mas na máquina de onde veio a solicitação, havia apenas metade do índice. O resto estava em outros servidores. Portanto, o servidor teve que ir para alguma máquina vizinha. Após receber os dados de ambos os servidores, os resultados foram combinados e reclassificados.

Como o balanceador distribui as solicitações uniformemente, todos os servidores estavam envolvidos na reclassificação, e não apenas no envio de dados.

O problema ocorria se um servidor vizinho não estivesse disponível. A solução foi especificar vários servidores com prioridades diferentes como servidores “vizinhos”. Primeiramente, a solicitação foi enviada aos servidores do rack atual. Caso não houvesse resposta, a solicitação era enviada a todos os servidores deste data center. E por último, a solicitação foi para outros data centers.
À medida que crescia o número de propostas, os dados foram divididos em quatro partes. Mas este não foi o limite.

Atualmente, é usada uma configuração de oito shards. Além disso, para economizar ainda mais memória, o índice foi dividido em uma parte de pesquisa (que é usada para pesquisar) e uma parte de snippet (que não está envolvida na pesquisa).

Um servidor contém informações de apenas um fragmento. Portanto, para pesquisar o índice completo, você precisa pesquisar em oito servidores contendo fragmentos diferentes.

Os servidores são agrupados em clusters. Cada cluster contém oito mecanismos de pesquisa e um servidor de snippet.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar
O servidor de snippet executa um banco de dados de valores-chave com dados estáticos. Eles são necessários para emitir documentos, por exemplo, a descrição de um gato com guincho. Os dados são transferidos especialmente para um servidor separado para não sobrecarregar a memória dos servidores de busca.

Como os IDs dos documentos são exclusivos apenas em um índice, pode surgir uma situação em que não haja documentos nos snippets. Bem, ou isso para um ID haverá conteúdo diferente. Portanto, para que a busca funcionasse e os resultados fossem retornados, era necessária consistência em todo o cluster. Vou contar a seguir como monitoramos a consistência.

A pesquisa em si está estruturada da seguinte forma: uma solicitação de pesquisa pode chegar a qualquer um dos oito servidores. Digamos que ele chegou ao servidor 1. Este servidor processa todos os argumentos e entende o que e como procurar. Dependendo da solicitação recebida, o servidor pode fazer solicitações adicionais a serviços externos para obter as informações necessárias. Uma solicitação pode ser seguida por até dez solicitações a serviços externos.

Após coletar as informações necessárias, inicia-se uma busca no banco de dados de ofertas. Para fazer isso, são feitas subconsultas em todos os oito servidores do cluster.

Depois que as respostas são recebidas, os resultados são combinados. No final, podem ser necessárias várias outras subconsultas ao servidor de snippet para gerar os resultados.

As consultas de pesquisa no cluster são semelhantes a: /shard1?text=zangado+gato. Além disso, subconsultas do formulário são feitas constantemente entre todos os servidores do cluster, uma vez por segundo: / status.

Pedido / status detecta uma situação em que o servidor não está disponível.

Ele também controla se a versão do mecanismo de pesquisa e a versão do índice são iguais em todos os servidores, caso contrário, haverá dados inconsistentes dentro do cluster.

Apesar do fato de um servidor de snippet processar solicitações de oito mecanismos de pesquisa, seu processador é pouco carregado. Portanto, agora estamos transferindo os dados do snippet para um serviço separado.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Para transferir dados, introduzimos chaves universais para documentos. Agora é impossível uma situação em que o conteúdo de outro documento seja retornado usando uma chave.

Mas a transição para outra arquitetura ainda não está completa. Agora queremos nos livrar do servidor de snippet dedicado. E então afaste-se completamente da estrutura de cluster. Isso nos permitirá continuar a escalar facilmente. Um bônus adicional é uma economia significativa de ferro.

E agora vamos às histórias assustadoras com finais felizes. Consideremos vários casos de indisponibilidade do servidor.

Algo terrível aconteceu: um servidor está indisponível

Digamos que um servidor esteja indisponível. Então, os servidores restantes no cluster poderão continuar a responder, mas os resultados da pesquisa ficarão incompletos.

Através da verificação de status / status servidores vizinhos entendem que um não está disponível. Portanto, para manter a integridade, todos os servidores no cluster por solicitação / ping eles começam a responder ao balanceador que também estão indisponíveis. Acontece que todos os servidores do cluster morreram (o que não é verdade). Esta é a principal desvantagem do nosso esquema de cluster – é por isso que queremos fugir dele.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

As solicitações que falham com erro são reenviadas pelo balanceador em outros servidores.
O balanceador também para de enviar tráfego de usuários para servidores inativos, mas continua verificando seu status.

Quando o servidor fica disponível, ele começa a responder a / ping. Assim que as respostas normais aos pings de servidores inativos começam a chegar, os balanceadores começam a enviar o tráfego do usuário para lá. A operação do cluster foi restaurada, viva.

Pior ainda: muitos servidores estão indisponíveis

Uma parte significativa dos servidores do data center está desligada. O que fazer, para onde correr? O balanceador vem em socorro novamente. Cada balanceador armazena constantemente na memória o número atual de servidores ativos. Ele calcula constantemente a quantidade máxima de tráfego que o data center atual pode processar.

Quando muitos servidores em um data center ficam inativos, o balanceador percebe que esse data center não pode processar todo o tráfego.

Então o excesso de tráfego começa a ser distribuído aleatoriamente para outros data centers. Tudo funciona, todos estão felizes.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Como fazemos: publicando lançamentos

Agora vamos falar sobre como publicamos as alterações feitas no serviço. Aqui seguimos o caminho da simplificação de processos: o lançamento de uma nova versão é quase totalmente automatizado.
Quando um determinado número de alterações é acumulado no projeto, uma nova versão é criada automaticamente e sua construção é iniciada.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Em seguida, o serviço é lançado para testes, onde é verificada a estabilidade do funcionamento.

Ao mesmo tempo, são lançados testes automáticos de desempenho. Isso é tratado por um serviço especial. Não vou falar sobre isso agora - sua descrição merece um artigo separado.

Se a publicação em teste for bem-sucedida, a publicação da versão em pré-estável será iniciada automaticamente. Prestable é um cluster especial para onde o tráfego normal do usuário é direcionado. Se retornar um erro, o balanceador faz uma nova solicitação à produção.

No pré-estável, os tempos de resposta são medidos e comparados com a versão anterior em produção. Se tudo estiver bem, uma pessoa se conecta: verifica os gráficos e os resultados dos testes de carga e depois começa a implementar a produção.

Tudo de bom vai para o usuário: teste A/B

Nem sempre é óbvio se as alterações num serviço trarão benefícios reais. Para medir a utilidade das mudanças, as pessoas criaram testes A/B. Vou contar um pouco sobre como funciona na pesquisa Yandex.Market.

Tudo começa com a adição de um novo parâmetro CGI que permite novas funcionalidades. Seja nosso parâmetro: market_new_funcionalidade=1. Então, no código, habilitamos esta funcionalidade se o sinalizador estiver presente:

If (cgi.experiments.market_new_functionality) {
// enable new functionality
}

Novas funcionalidades estão sendo lançadas em produção.

Para automatizar os testes A/B, existe um serviço dedicado que fornece informações detalhadas descrito aqui. Um experimento é criado no serviço. A participação do tráfego é definida, por exemplo, em 15%. As porcentagens não são definidas para consultas, mas para usuários. A duração do experimento também é indicada, por exemplo, uma semana.

Vários experimentos podem ser executados simultaneamente. Nas configurações você pode especificar se a interseção com outros experimentos é possível.

Como resultado, o serviço adiciona automaticamente um argumento market_new_funcionalidade=1 para 15% dos usuários. Ele também calcula automaticamente as métricas selecionadas. Após a conclusão do experimento, os analistas analisam os resultados e tiram conclusões. Com base nas descobertas, é tomada a decisão de implantá-lo em produção ou refinamento.

A mão hábil do mercado: testes em produção

Muitas vezes acontece que você precisa testar a operação de uma nova funcionalidade em produção, mas não tem certeza de como ela se comportará em condições de “combate” sob carga pesada.

Existe uma solução: sinalizadores em parâmetros CGI podem ser usados ​​não apenas para testes A/B, mas também para testar novas funcionalidades.

Criamos uma ferramenta que permite alterar instantaneamente a configuração em milhares de servidores sem expor o serviço a riscos. Chama-se Stop Tap. A ideia original era poder desabilitar rapidamente algumas funcionalidades sem layout. Depois a ferramenta se expandiu e ficou mais complexa.

O diagrama de fluxo de atendimento é apresentado a seguir:

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Os valores dos sinalizadores são definidos por meio da API. O serviço de gerenciamento armazena esses valores no banco de dados. Todos os servidores vão ao banco de dados uma vez a cada dez segundos, bombeiam valores de sinalizadores e aplicam esses valores a cada solicitação.

Na torneira Stop você pode definir dois tipos de valores:

1) Expressões condicionais. Aplicar quando um dos valores for verdadeiro. Por exemplo:

{
	"condition":"IS_DC1",
	"value":"3",
}, 
{
	"condition": "CLUSTER==2 and IS_BERU", 
	"value": "4!" 
}

O valor “3” será aplicado quando a solicitação for processada no local DC1. E o valor é “4” quando a solicitação é processada no segundo cluster do site beru.ru.

2) Valores incondicionais. Aplicar por padrão se nenhuma das condições for atendida. Por exemplo:

valor, valor!

Se um valor terminar com um ponto de exclamação, ele terá prioridade mais alta.

O analisador de parâmetros CGI analisa o URL. Em seguida, aplica os valores do Stop Tap.

São aplicados valores com as seguintes prioridades:

  1. Com maior prioridade do Stop Tap (ponto de exclamação).
  2. O valor da solicitação.
  3. Valor padrão de Stop tap.
  4. Valor padrão no código.

Existem muitos sinalizadores indicados em valores condicionais - eles são suficientes para todos os cenários que conhecemos:

  • Centro de dados.
  • Ambiente: produção, teste, sombra.
  • Local: mercado, beru.
  • Número do cluster.

Com esta ferramenta, você pode habilitar novas funcionalidades em um determinado grupo de servidores (por exemplo, em apenas um data center) e testar o funcionamento desta funcionalidade sem nenhum risco particular para todo o serviço. Mesmo que você tenha cometido um erro grave em algum lugar, tudo começou a cair e todo o data center caiu, os balanceadores redirecionarão as solicitações para outros data centers. Os usuários finais não notarão nada.

Se você notar um problema, poderá retornar imediatamente o sinalizador ao valor anterior e as alterações serão revertidas.

Este serviço também tem suas desvantagens: os desenvolvedores o adoram e muitas vezes tentam inserir todas as alterações no Stop Tap. Estamos tentando combater o uso indevido.

A abordagem Stop Tap funciona bem quando você já tem um código estável pronto para ser implementado em produção. Ao mesmo tempo, você ainda tem dúvidas e deseja verificar o código em condições de “combate”.

No entanto, Stop Tap não é adequado para testes durante o desenvolvimento. Existe um cluster separado para desenvolvedores chamado “cluster shadow”.

Teste secreto: Shadow Cluster

As solicitações de um dos clusters são duplicadas para o cluster shadow. Mas o balanceador ignora completamente as respostas deste cluster. O diagrama de seu funcionamento é apresentado a seguir.

Como funciona a pesquisa Yandex.Market e o que acontece se um dos servidores falhar

Obtemos um cluster de teste que está em condições reais de “combate”. O tráfego normal do usuário vai para lá. O hardware em ambos os clusters é o mesmo, portanto o desempenho e os erros podem ser comparados.

E como o balanceador ignora completamente as respostas, os usuários finais não verão as respostas do shadow cluster. Portanto, não é assustador cometer um erro.

Descobertas

Então, como construímos a busca de mercado?

Para que tudo corra bem, separamos a funcionalidade em serviços separados. Dessa forma, podemos dimensionar apenas os componentes de que precisamos e torná-los mais simples. É fácil atribuir um componente separado a outra equipe e compartilhar as responsabilidades de trabalhar nele. E economias significativas de ferro com essa abordagem são uma vantagem óbvia.

O shadow cluster também nos ajuda: podemos desenvolver serviços, testá-los no processo e não incomodar o usuário.

Bem, testando em produção, é claro. Precisa alterar a configuração em milhares de servidores? Fácil, use o Stop Tap. Dessa forma, você pode implementar imediatamente uma solução complexa pronta e reverter para uma versão estável se surgirem problemas.

Espero ter conseguido mostrar como tornamos o Mercado rápido e estável com uma base de ofertas cada vez maior. Como resolvemos problemas de servidor, lidamos com um grande número de solicitações, melhoramos a flexibilidade do serviço e fazemos isso sem interromper os processos de trabalho.

Fonte: habr.com

Adicionar um comentário