Aquecimento de cache: agilidade para um serviço com estado

Netflix Technology Blog Blocked Unblock Seguir Seguindo 4 de dezembro de 2018

por Deva Jayaraman , Shashi Madappa , Sridhar Enugula e Ioannis Papapanagiotou

O EVCache tem sido uma parte fundamental da plataforma Netflix (nós chamamos isso de Camada 1), mantendo Petabytes de dados. Nossa camada de armazenamento em cache atende a vários casos de uso, desde inscrição, personalização, pesquisa, reprodução e muito mais. Ele é composto de milhares de nós em produção e centenas de clusters, os quais devem ser redimensionados rotineiramente devido ao crescimento crescente de nossos membros. Para atender à alta demanda de nosso armazenamento em cache, recentemente discutimos a evolução do armazenamento de dados de aplicativos: da RAM ao SSD .

A capacidade de armazenamento do cache pode ser aumentada através da expansão ou ampliação (em alguns casos, da RAM para o SSD). Muitos serviços executam trilhões de consultas por dia, o que enfatiza a capacidade de rede de nossa infraestrutura de armazenamento em cache. Quando precisávamos escalar o cache devido ao armazenamento ou à demanda da rede, nossa abordagem era provisionar um novo cache vazio, gravação dupla no cache existente e no novo, e depois permitir que os dados expirassem no cluster mais antigo após o cache. Tempo de vida (TTL). Essa metodologia funcionou bem. Mas para cada atividade de aumento de escala, tivemos que pagar o custo adicional de manter o cluster antigo e o cluster recém dimensionado pela duração do TTL. Essa abordagem não se adequava bem aos clusters que tinham itens sem tempo de expiração ou que não sofriam mutação. Além disso, o aquecimento natural de dados em nós que são substituídos em uma ou mais réplicas pode causar falhas de cache.

Fig.1 Caminho de dados do EVCache para novas implantações

Para resolver os problemas mencionados acima, apresentamos a infraestrutura de cache mais quente do EVCache com os seguintes recursos:

Réplica mais quente : um mecanismo para copiar dados de uma das réplicas existentes para as novas o mais rápido possível sem afetar os clientes usando as réplicas existentes.

Instância mais quente : um mecanismo para inicializar um nó depois de ter sido substituído ou finalizado usando dados de uma réplica que não contém esse nó.

Aquecedor de cache

As metas de design para o sistema de aquecimento de cache eram:

  • Limitar o impacto da rede nos clientes atuais do EVCache
  • Minimize a memória e o uso de disco nos nós do EVCache
  • Encurtar o tempo de aquecimento
  • Não tem restrições sobre quando (períodos de pico / não pico) para aquecer

Abordagens anteriores

Experimentamos várias abordagens de design para atender a esses requisitos.

Piggybacking na replicação

O modelo de implantação de nuvem da Netflix é ativo-ativo, o que significa que precisamos manter todos os clusters do EVCache em sincronia entre três regiões da AWS. Nós construímos um sistema de replicação entre regiões baseado em Kafka. Em nossa primeira iteração, pensamos que poderíamos usar as mensagens enfileiradas em Kafka para aquecer as novas réplicas. No entanto, um dos desafios com essa abordagem é que tivemos que armazenar as chaves pela duração do TTL (até algumas semanas), aumentando assim o custo. Também tivemos problemas com a deduplicação de chaves, especialmente com a invalidação.

Usando despejos de chave

Nessa abordagem, despejamos chaves e metadados de cada nó de uma réplica existente e os carregamos para o S3. O despejo de chave foi baseado no utilitário de rastreio LRU do Memcached. O despejo de chave seria então consumido pelo aplicativo populator de cache. O aplicativo de populador de cache faria o download do dump de chave do S3, depois buscaria os dados de cada chave de réplicas existentes e a preencheria nas novas réplicas.

Enquanto os dados estão sendo buscados pelo cache warmer das réplicas existentes, notamos que os clientes atuais foram impactados, pois o cache warmer teria compartilhado a mesma infraestrutura de rede com os clientes atuais. Isso teve um impacto nas operações atuais. Isso limitaria nossa capacidade de executar o aquecimento de cache durante os horários de pico e tivemos que introduzir um limitador de taxa para evitar congestionamento da rede usada pelos caches.

Projeto mais quente de cache

O diagrama abaixo mostra a visão geral da arquitetura do nosso atual sistema de aquecimento de cache. Tem três blocos principais – Controller , Dumper e Populator . Para fins de representação, não incluímos as partes responsáveis pelas tarefas de implantação, como criar / destruir clusters e o serviço de configuração, que fornece o ambiente para os serviços da Netflix.

Fig.2 Arquitetura do Cache Warmer

O controlador atua como o orquestrador. É responsável por criar o ambiente, canal de comunicação entre o Dumper e o Populator e limpar os recursos. O Dumper faz parte do sidecar da EVCache. O sidecar é um serviço do Tomcat que é executado junto com o memcached em cada nó do EVCache e é responsável por produzir dumps. O Populator consome os despejos produzidos pelo Dumper e o preenche nas réplicas de destino.

Controlador de Cache Warmer

A origem dos dados, ou seja, a réplica de onde os dados precisam ser copiados, pode ser fornecida pelo usuário ou o Controlador selecionará a réplica com o maior número de itens. O Controlador criará uma fila SQS dedicada que é usada como um link de comunicação entre o Dumper e o Populator . Em seguida, inicia o despejo de cache nos nós da réplica de origem. Enquanto o despejo está em andamento, o Controlador criará um novo cluster Populator . O Populator obterá a configuração, como o nome da fila do SQS e outras configurações. O Controlador aguardará até que as mensagens da fila do SQS sejam consumidas com sucesso pelo Populator . Quando a fila do SQS estiver vazia, ela destruirá o cluster do Populator , a fila do SQS e quaisquer outros recursos.

O dumper

Para limitar o impacto nos clientes existentes que estão acessando as réplicas do EVCache, adotamos a abordagem para despejar os dados em cada nó do EVCache. Cada nó faz o dumping dos dados em duas fases.

  1. Enumerar as chaves usando o utilitário de rastreador LRU do Memcached e despejar as chaves em muitos arquivos de chave-chave.
  2. Para cada chave no bloco de chaves, o Dumper recuperará seu valor e dados auxiliares e os despejará em um arquivo de dados-bloco local.

Quando o tamanho máximo do fragmento é atingido, o fragmento de dados é carregado no S3 e uma mensagem contendo o URI do S3 é gravada na fila do SQS. Os metadados sobre o fragmento de dados, como o ID de aquecimento, o nome do host, o URI do S3, o formato de dump e a contagem de chaves, são mantidos junto com o fragmento no S3. Isso permite o consumo independente dos blocos de dados. O tamanho configurável dos fragmentos de dados permite que eles sejam consumidos à medida que se tornam disponíveis, portanto, não esperando que o despejo inteiro seja concluído. Como haverá vários trechos de chave em cada nó EVCache, o dump de dados pode ser feito em paralelo. O número de encadeamentos paralelos depende do espaço em disco disponível, do tamanho de heap da JVM do sidecar e dos núcleos da CPU.

O Populador

O Populator é um trabalhador encarregado de preencher as réplicas de destino. Ele obtém as informações sobre a fila e a réplica de destino do SQS (opcional) por meio da propriedade dinâmica Archaius, que é configurada pelo Controlador . O Populator puxará a mensagem da fila do SQS. A mensagem contém o URI S3, faz o download do bloco de dados e começa a preencher os dados nas réplicas de destino. O Populator realiza operações de adição (ou seja, insere chaves somente se elas não estiverem presentes) para evitar sobrescrever as chaves que foram mutadas enquanto o aquecimento estava ocorrendo.

O Populator inicia seu trabalho assim que o despejo de dados estiver disponível. O cluster do Populator é dimensionado automaticamente, dependendo dos fragmentos de dados disponíveis na fila do SQS.

Instância mais quente

Em uma grande implantação do EVCache, é comum ter nós sendo finalizados ou substituídos pela AWS devido a problemas de hardware ou outros. Isso poderia causar picos de latência no aplicativo, porque o cliente EVCache precisaria buscar os dados ausentes de outras réplicas do EVCache. O aplicativo pode ver uma queda na taxa de acertos se os nós em várias réplicas forem afetados ao mesmo tempo.

Podemos minimizar o efeito de substituições de nós ou reinicializações se pudermos aquecer as instâncias substituídas ou reiniciadas muito rapidamente. Conseguimos estender nosso cache mais quente para obter o aquecimento da instância com poucas alterações no cache Dumper e adicionando um sinal dos nós do EVCache para notificar as reinicializações.

Fig.3 Arquitetura mais quente da instância

O diagrama ilustra a arquitetura por exemplo aquecimento, aqui temos três réplicas EVCache. Um dos nós na réplica, mostrado no meio, é reiniciado indicado pela cor vermelha e precisa ser aquecido.

Quando o Controlador recebe um sinal de um nó EVCache na inicialização, ele verifica se algum nó na réplica relatada tem menos do que seu quinhão de vezes, se for o caso, ele acionará o processo de aquecimento. O controlador garante não usar a réplica relatada como a réplica de origem. O EVCache usa hashing consistente com nós virtuais. Os dados em um nó reiniciado / substituído são distribuídos em todos os nós nas outras réplicas, portanto, precisamos despejar dados em todos os nós. Quando o Controlador inicia o despejo, ele passará pelos nós específicos que precisam ser aquecidos e pela réplica à qual eles pertencem. O Dumper descarregará os dados apenas para as chaves que serão agrupadas em nós específicos. O Populator consumirá os blocos de dados para preencher os dados para a réplica específica, conforme explicado anteriormente.

O processo de aquecimento da instância é muito mais leve que o aquecimento da réplica, já que lidamos com uma fração de dados em cada nó.

Na prática

O cache warmer está sendo amplamente usado para escalar nossos caches se o seu TTL for maior que algumas horas. Isso tem sido especialmente útil quando dimensionamos nossos caches para lidar com o tráfego de fim de ano.

O gráfico abaixo mostra o aquecimento de duas novas réplicas de uma das duas réplicas existentes. As réplicas existentes tinham cerca de 500 milhões de itens e 12 terabytes de dados. O aquecimento foi concluído em cerca de 2 horas.

Fig.4 Cache warmer em ação

O maior cache que temos aquecido é de cerca de 700 TB e 46 bilhões de itens. Esse cache tinha 380 réplicas de nós. A cópia do cache levou cerca de 24 horas com 570 instâncias populator.

O aquecedor de instâncias está sendo empregado na produção e está aquecendo algumas instâncias todos os dias. Abaixo do gráfico é um exemplo, por exemplo, do aquecimento, aqui uma instância foi substituída por volta de 5,27, foi aquecida em menos de 15 minutos com cerca de 2,2 GB de dados e 15 milhões de itens. O tamanho médio dos dados e a contagem de itens para a réplica também são mostrados no gráfico.

Fig.5 Aquecedor de instâncias em ação

Melhorias futuras

Escalonamento elástico : O mecanismo de aquecimento de instância automática descrito acima abre a possibilidade de expandir o EVCache em escala (ou dimensionar). Isso nos poupará custos e tempo para grandes implantações de EVCache, pois evita a necessidade de criar uma nova réplica e aquecer. O principal desafio é reduzir o impacto nos clientes existentes devido a alterações no hashing e outras operações administrativas, como a limpeza de chaves órfãs.

Armazenamento de EBS : O principal gargalo com a abordagem atual de lidar com um cache muito grande é o upload e o download de blocos de dados de e para o S3. Observamos que a largura de banda da rede S3 é acelerada após um determinado período. Uma alternativa melhor seria usar o armazenamento suportado pelo EBS para armazenar e recuperar blocos de dados. A ideia é que o Dumper em cada nó seja capaz de se conectar a um volume do EBS e enviar os dados para um local conhecido. O Populator pode anexar o mesmo volume do EBS e fazer a adição a novas réplicas. Nós precisaríamos da capacidade de várias instâncias se anexarem ao mesmo volume de EBS, se quisermos executar o Dumper e o Populator simultaneamente, para fazer um aquecimento rápido.

Adaptando-se a outros armazenamentos de dados : nossa equipe também oferece suporte a outros sistemas de armazenamento de dados de alto desempenho, como o Dynomite, que está à frente de nossa infra-estrutura Redis. Estaremos investigando se alguns dos componentes poderiam ser aproveitados para a escalabilidade horizontal da Dynomite.

Conclusão

Neste blog, discutimos a arquitetura da nossa infraestrutura de aquecimento de cache. A arquitetura flexível de aquecimento de cache nos permitiu copiar dados de réplicas existentes para mais uma nova réplica e aquecer os nós que foram terminados ou substituídos devido a problemas de hardware. Nossa arquitetura também nos permitiu controlar o ritmo de aquecimento do cache devido ao fraco acoplamento entre o Dumper do cache e o Populator e várias configurações de ajuste configuráveis. Temos usado o cache mais quente para escalar e aquecer os caches por alguns meses e planejamos estendê-lo para suportar outros sistemas.

Texto original em inglês.