Aplicativo de armazenamento de dados usando SSDs

Aplicativo de armazenamento de dados usando SSDs

A tecnologia que a Netflix emprega, a metodologia de desenvolvimento e os
inúmeros projetos open source que eles disponibilizam para a comunidade a fim de melhorarem
seus serviços tem atraido a atenção de leitores de todo o mundo para o seu techblog.
Neste artigo, teremos uma explicação de como a Netflix consegue manter a personalização dos dados dos
seus clientes em qualquer parte do mundo. Basicamente é o modo como eles mantêm a persistência
e a replicação dos dados personalizados de 81 milhões de usuários, o que, embora não seja algo
comum, é um estudo de caso interessante para explicar como eles trabalham o custo-benefício, o
balanceamento do armazenamento, a importância dos testes A/B, as aplicações em produção e o
aumento da performance causado pelo impacto do projeto. E tudo isso de uma maneira open source
que você pode ajudar a construir.
Vamos falar do projeto Moneta, o EVCache de próxima geração para uma melhor otimização de
custos.
Com a expansão global da Netflix no início deste ano, veio a expansão global dos dados. Depois do
projeto Active-Active e agora com a arquitetura N+1, os dados personalizados mais recentes
precisam estar em todos os lugares em todos os momentos para servir qualquer membro de qualquer
região. O caching desempenha um papel crítico na história de persistência para personalização aos
membros conforme detalhado neste artigo do blog.
Há dois componentes principais para a arquitetura Netflix. O primeiro é o plano de controle que é
executado na nuvem AWS para ser uma computação genérica, escalável para a experiência de
inscrição do membro, de navegação e reprodução. O segundo é o plano de dados, chamado Open
Connect, que é a rede de distribuição de vídeo global que eles utilizam. Este artigo fala sobre como
eles trouxeram o poder e a economia do SSDs para o EVCache – o sistema de cache primário em
uso na Netflix para aplicativos executados no plano de controle na AWS.
Um dos principais casos de uso de EVCache é agir como armazenamento globalmente replicado
para os dados personalizados para cada um dos mais de 81 milhões de membros da Netflix.
EVCache desempenha uma variedade de papéis dentro da Netflix, além de reter esses dados,
inclusive atuando como um cache de conjunto de trabalho padrão para coisas como as informações
do assinante. Mas o seu maior papel é para a personalização. Servir qualquer pessoa de qualquer
lugar significa que eles têm que manter todos os dados personalizados para cada membro em cada
uma das três regiões em que operam. Isso permite uma experiência consistente em todas as regiões
da AWS e permite aos devs da Netflix mudar facilmente de tráfego durante as interrupções
regionais ou durante tráfego regular, moldando exercícios para balancear a carga. Eles falaram
longamente sobre o sistema de replicação usado para fazer isso acontecer em um texto anterior.
Durante o estado estacionário, as regiões tendem a ver os mesmos membros várias vezes.Entretanto, alternar entre regiões não é um fenômeno muito comum para os seus usuários. Mesmo
que seus dados estejam na memória RAM em todas as três regiões, apenas uma região está sendo
usada regularmente pelo membro. Extrapolando a partir disso, é possível ver que cada região tem
um conjunto de trabalho diferente para esses tipos de caches. Um pequeno subconjunto são dados
quentes, e o resto é frio.
Além da separação de dados quente/frio, o custo de manter todos esses dados na memória está
crescendo junto com a base de membros. Assim, os diferentes testes A/B e outras mudanças internas
podem adicionar ainda mais dados. Para o conjunto de trabalho de membros, eles já possuem
milhares de milhões de chaves, e esse número só tende a crescer. Existe o desafio de continuar a
apoiar os casos de uso do Netflix, equilibrando custo. Para enfrentar esse desafio, está sendo
introduzindo um esquema de cache multi-nível usando RAM e SSD.
O projeto EVCache, para tirar proveito dessa distribuição entre pedido e custo de otimização global,
é chamado de Moneta, em homenagem à deusa latina da memória, e Juno Moneta, a protetora de
fundos para Juno.

Arquitetura atual
Agora, vou abordar a arquitetura atual dos servidores EVCache e, em seguida, falar sobre como isso
está evoluindo para ativar o suporte SSD.
A figura abaixo mostra uma implementação típica para EVCache e a relação entre uma instância de
cliente única e os servidores. Um cliente da EVCache vai conectar vários clusters de servidores
EVCache. Em uma região, há várias cópias de todo o conjunto de dados, separados por Zona de
disponibilidade AWS. As caixas tracejadas delineiam as réplicas em região, com cada uma tendo
uma cópia completa dos dados e agindo como uma unidade. Eles administram essas cópias como
grupos separados de autoescalabilidade AWS. Alguns caches têm duas cópias por região, e alguns
têm muitas. Essa arquitetura de alto nível ainda é válida para a Netflix para o futuro previsível, e
não está mudando. Cada cliente se conecta a todos os servidores em todas as zonas em sua própria
região. As gravações são enviadas para todas as cópias e leituras, preferencialmente em servidores
topologicamente perto das solicitações de leitura. Para ver mais detalhes sobre a arquitetura
EVCache, veja este texto.
O servidor, à medida que vem evoluindo ao longo dos últimos anos, é uma coleção de alguns
processos, com dois principais: stock Memcached, um armazenamento popular e muito testado dekey-value in-memory, e Prana, o processo paralelo da Netflix. Prana é o gancho do servidor para o
resto do ecossistema da Netflix, que ainda é essencialmente baseado em Java. Os clientes se
conectam diretamente no processo Memcached rodando em cada servidor. Os servidores são
independentes e não se comunicam uns com os outros.

gmvgrkqedhhqfiqeqfuuryw5kwhwwoh-vcy3wcmap9ucvrucxk18cqokmakxsnz-c3mpras2048

 

Otimização
Como um dos maiores subsistemas da nuvem Netflix, eles estão em uma posição única para aplicar
otimizações através de uma percentagem significativa de nossa nuvem. O custo de manter todos os
dados armazenados na memória está crescendo junto com a base de membros. A saída de um único
estágio do processo de lote de personalização de um único dia pode carregar mais de 5 terabytes de
dados em seu conjunto EVCache dedicado. O custo de armazenar esses dados é multiplicado pelo
número de cópias globais de dados que armazenam. Como mencionado anteriormente, os diferentes
testes A/B e outras mudanças internas podem adicionar ainda mais dados. Para apenas o conjunto de
trabalho de membros da Netflix, hoje eles têm muitos milhares de milhões de chaves.
Para aproveitar os diferentes padrões de acesso a dados que eles observaram em diferentes regiões,
eles construíram um sistema para armazenar os dados quentes na RAM e os dados frios no disco.
Esse é a clássica arquitetura de cache um de dois níveis (onde L1 é RAM, e L2 é disco), mas os
engenheiros da Netflix têm confiado no desempenho consistente e na baixa latência do EVCache.
Os requisitos deles se resumem a ter a maior baixa latência possível, usar uma quantidade mais
equilibrada do (caro) RAM, e tirar proveito do armazenamento SSD de baixo custo, enquanto
entregam a baixa latência que seus usuários esperam.
Clusters In-memory EVCache são executados na família de tipo de instância AWS R3, que são
otimizados para grande uso de memória. Movendo para a família i2 de instâncias, eles conseguem
um ganho de acesso 10 vezes a quantidade de armazenamento mais rápido SSD que possuíam na
família R3 (80 → 800GB de r3.xlarge para i2.xlarge) com o equivalente de RAM e CPU. Também
foi possível rebaixar os tamanhos da instância para uma menor quantidade de memória.
Combinando esses dois, eles conseguiram um potencial de otimização substancial de custos em seus
muitos milhares de servidores.

 

Arquitetura Moneta
O projeto Moneta introduz dois novos processos no servidor EVCache: Rend e Mnemonic. Rend é
um proxy de alta performance escrito em Go com o caso de uso da Netflix como o principal motor
para o desenvolvimento. Mnemonic é um armazenamento de key-value baseado em disco e noRocksDB. Mnemonic reutiliza os componentes do servidor Rend que lidam com protocolo de
análise (para falar com os protocolos Memcached), gerenciamento de conexão e de bloqueio
paralelo (para correção). Todos os três servidores, na verdade, falam o protocolo de texto e binários
do Memcached, de modo que as interações com o cliente entre qualquer um dos três têm a mesma
semântica. Eles utilizam isso a seu favor quando depuram ou fazem a verificação de consistência.

gyp8yua0s7kuletajhtpjvsrygfi6yoehbb9o3yzkxoo1wrzya7l0_6vge44gw_pcxlgrgs2048
Onde os clientes previamente se conectavam ao Memcached diretamente, eles agora se conectam ao
Rend. A partir daí, Rend cuida das interações L1/L2 entre Memcached e Mnemonic. Mesmo em
servidores que não usam Mnemonic, Rend ainda fornece métricas valiosas do lado do servidor que
não podiam ser obtidas antes a partir do Memcached, como latências de solicitação do servidor. A
latência introduzida por Rend, em conjunto com apenas Memcached, em média é apenas algumas
dezenas de microssegundos.
Como parte dessa reformulação, seria possível ter integrado os três processos em conjunto. Eles
escolheram ter três processos independentes em execução em cada servidor para manter a separação
de interesses. Essa configuração proporciona uma melhor durabilidade de dados no servidor. Se o
Rend falhar, os dados ainda estarão intactos no Memcached e no Mnemonic. O servidor é capaz de
atender às solicitações dos clientes, uma vez que se reconecta a um processo Rend ressuscitado. Se
Memcached falhar, eles perdem o conjunto de trabalho, mas os dados no L2 (Mnemonic) ainda
estarão disponíveis. Uma vez que os dados são solicitados novamente, ele estará de volta no
conjunto quente e servido como era anteriormente. Se Mnemonic cair, ele não iria perder todos os
dados, mas apenas eventualmente um pequeno conjunto que foi escrito muito recentemente. Mesmo
que tenha perdido os dados, pelo menos eles têm os dados quentes ainda na RAM e disponíveis para
os usuários que utilizam o serviço. Essa resiliência a falhas está no topo das medidas de resiliência
no cliente EVCache.

 

Rend
Rend, como mencionado acima, funciona como um proxy na frente dos dois outros processos no
servidor que realmente armazenam os dados. É um servidor de alto desempenho que fala os
protocolos Memcached binários e de texto. Ele é escrito em Go e depende fortemente de goroutines
e outras primitivas de linguagem para lidar com a concorrência. O projeto é totalmente de código
aberto e está disponível no GitHub. A decisão de usar Go foi deliberada, porque eles precisavam de
algo que tivesse latência mais baixa do que Java (onde pausas de garbage collection são umproblema), fosse mais produtivo para os desenvolvedores do que C, e ao mesmo tempo, lidasse com
dezenas de milhares de conexões do cliente. Go se encaixa bem nesse espaço.
Rend tem a responsabilidade de gerir a relação entre os caches L1 e L2 na caixa. Ele tem algumas
políticas internas diferentes que se aplicam a diferentes casos de uso. Ele também possui um recurso
para cortar dados em pedaços de tamanho fixo enquanto os dados estão sendo inseridos no
Memcached para evitar comportamento patológico do esquema de alocação de memória dentro
Memcached. Esse chunking do lado do servidor está substituindo a atual versão do lado do cliente,
e já está se mostrando promissor. Até agora, é duas vezes mais rápido para leituras e até 30 vezes
mais rápido para as gravações. Felizmente, Memcached, a partir do 1.4.25, tornou-se muito mais
resistente ao comportamento do cliente ruim que causou problemas anteriormente. Assim é
permissível retirar o recurso chunking no futuro, enquanto eles podem depender de L2 para ter os
dados, se forem despejados de L1.

 

Design
O design do Rend é modular para permitir funcionalidades configuráveis. Internamente, existem
algumas camadas: gerenciamento de conexão, um loop de servidor, o código específico do
protocolo, o pedido de orquestração e manipuladores de backend. De um lado, é um pacote de
métricas personalizadas que permite Prana, um processo paralelo, pegar as métricas de informações
não sendo demasiado intrusivo. Rend também vem com uma biblioteca de cliente de teste que tem
uma base de código separada. Isso os têm ajudado a encontrar bugs de protocolo ou outros erros,
tais como: desalinhamento, buffers unflushed e respostas inacabadas.

gsqwuiw87-hqwmwqcyrdoyqvgjaoc6virdxvp_p2fa4lh1qsboqnxmis1x_h9jxk0gz3qqs2048
O design do Rend permite que diferentes backends possam ser ligados com o cumprimento de uma
interface e uma função do construtor. Para provar esse projeto, um engenheiro familiarizado com a
base de código levou menos de um dia para aprender LMDB e integrar como um backend de
armazenamento. O código para essa experiência pode ser encontrado em
https://github.com/Netflix/rend-lmdb.

 

Uso em produção
Para os caches que Moneta serve melhor, há algumas diferentes classes de clientes que servem um
único servidor. Uma classe é o tráfego online no caminho quente, solicitando dados de
personalização para um membro visitante. O outro é o tráfego dos sistemas offline e nearline queproduzem dados de personalização. Estes normalmente são executados em grandes lotes durante a
noite e continuamente escrevem por horas a fio.
A modularidade permite que a implementação padrão otimize a computação em lote noturno através
da inserção de dados em L2 diretamente e substituindo de forma inteligente dados quentes no L1,
em vez de deixar essas gravações consumirem o cache L1 durante o precompute noturno. Os dados
replicados vindos de outras regiões também podem ser inseridos diretamente em L2, já que é
improvável que os dados replicados e outra região sejam “quentes” em sua região de destino. O
diagrama abaixo mostra as várias portas abertas em um processo de Rend em que ambas se ligam
nas backing stores. Com a modularidade do Rend, foi fácil introduzir outro servidor em uma porta
diferente para o lote e o tráfego de replicação com apenas mais um par de linhas de código.

hpkzx75vyrvjvl2h-pmivpmoq9qkqmehmzs7c-3ppl_mqvunoo_wu3elyim5yzs0azsfdas2048

Performance
Rend por si só, é de muito alto rendimento. Ao testar Rend separadamente, eles sempre batem o
limite da largura de banda ou de processamento de pacotes antes de estourar o limite da CPU. Um
único servidor, para os pedidos que não precisam pegar nada do backing store, tem atingido 2.86
milhões de pedidos por segundo. Essa é uma estimativa, mas um número irrealista. Com
Memcached como o único backing storage, Rend pode sustentar 225k inserções por segundo e 200
mil leituras por segundo simultaneamente no maior exemplo que eles testaram. Uma instância
i2.xlarge configurada para usar ambos L1 e L2 (memória e disco) e dados chunking, que é utilizado
como um exemplo padrão para os nossos grupos de produção, pode realizar 22k inserções por
segundo (com apenas sets), 21K leituras por segundo (apenas com gets), e cerca de 10 mil sets e
10k gets por segundo se ambos forem feitos simultaneamente. Estes são os mais baixos limites para
o tráfego de produção deles, porque a carga de teste consistiu em chaves aleatórias não
proporcionando benefícios de localidade de dados durante o acesso. Tráfego real vai bater o cache
L1 com muito mais frequência do que chaves aleatórias poderiam fazer.
Como uma aplicação do lado do servidor, Rend desbloqueia todos os tipos de possibilidades futuras
para a inteligência no servidor EVCache. Além disso, o armazenamento subjacente é
completamente desconectado do protocolo usado para se comunicar. Dependendo das necessidades
do Netflix, eles podem mover o armazenamento L2 off-box, substituindo o Memcached L1 por
outro armazenamento, ou alterar a lógica do servidor para adicionar bloqueio global ou
consistência. Estes não são projetos previstos, mas eles são possíveis agora que possuem o códigopersonalizado em execução no servidor.

 

Mnemonic
Mnemonic é a solução L2 baseada no RocksDB. Ele armazena dados no disco. A análise de
protocolo, gerenciamento de conexão e controle de concorrência do Mnemonic são gerenciados
pelas mesmas bibliotecas que abastecem o Rend. Mnemonic é outro backend que está conectado a
um servidor Rend. As bibliotecas nativas no projeto Mnemonic expõem uma API personalizada C
que é consumida por um manipulador Rend.
As partes interessantes do Mnemonic estão na camada do núcleo C++ que envolve o RocksDB.
Mnemonic processa os pedidos de estilo Memcached, implementando cada uma das operações
necessárias para estar em conformidade com o comportamento Memcached, incluindo suporte TTL.
Ele inclui uma característica mais importante: quebra as solicitações entre vários bancos de dados
RocksDB em um sistema local para reduzir o trabalho de cada instância individual do RocksDB. As
razões por que faz isso serão exploradas na próxima seção.

 

RocksDB
Depois de olhar para algumas opções de forma eficiente para acessar SSDs, o Netflix escolheu o
RocksDB, um armazenador de key-value embutido que usa um design de estrutura de dados de
árvore de mesclagem log estruturado (Log Strutured Merge Tree). As operações de gravação são
primeiramente inseridas em uma estrutura de dados na memória (memtable) que é descarregada
para o disco quando ela estiver cheia. Quando liberada para o disco, o memtable torna-se um
arquivo de SST imutável. Isso faz com que a maioria seja escrita sequencialmente para o SSD, o
que reduz a quantidade de garbage collection interno que o SSD deve executar e, assim, melhorar a
latência em instâncias longas de funcionamento, ao mesmo tempo reduzindo o desgaste.
Um tipo de trabalho que é feito em segundo plano por cada instância separada do RocksDB inclui
compactação. Eles inicialmente utilizaram o nível de configuração de compactação por estilo (style
compaction), que foi a principal razão para fragmentar os pedidos em vários bancos de dados. No
entanto, enquanto estavam avaliando essa configuração de compactação com dados de produção e
tráfego de produção, descobriram que a compactação estava causando uma grande quantidade de
tráfego extra de leitura/gravação para o SSD, aumentando as latências que no passado pensavam ser
aceitáveis. O tráfego de leitura SSD ultrapassou algumas vezes 200MB/seg. Esse tráfego deavaliação incluiu um período prolongado em que o número de operações de gravação foi alta,
simulando processos diários de computação em lotes. Durante esse período, RocksDB estava
constantemente movendo novos registros L0 nos níveis mais elevados, provocando uma
amplificação muito elevada de escrita.
Para evitar essa sobrecarga, eles transferiram para a compactação estilo FIFO. Nessa configuração,
nenhuma operação de compactação verdadeira é feita. Arquivos SST antigos são excluídos com
base no tamanho máximo do banco de dados. Registros ficam no disco no nível 0, de modo que os
registros só são ordenados por tempo entre os múltiplos arquivos de SST. A desvantagem dessa
configuração é que uma operação de leitura deve verificar cada arquivo de SST em ordem
cronológica inversa antes de uma tecla ser determinada como faltando. Essa verificação geralmente
não requer uma leitura de disco, já que os filtros bloom do RocksDB evitam que altas porcentagens
das consultas exijam um acesso em disco a cada SST. No entanto, o número de arquivos de SST faz
com que a eficácia global do conjunto de filtros de bloom seja menor do que o estilo normal de
compactação. A fragmentação inicial das entradas de leitura e escrita pedidas através das várias
instâncias RocksDB ajudam a diminuir o impacto negativo na digitalização de tantos arquivos.

 

Performance
Reexecutando o teste de avaliação com a configuração final de compactação, eles foram capazes de
alcançar uma latência de 99% de ~9ms para consultas de leitura durante a carga precompute. Após a
carga precompute ser concluída, o percentual de 99 de latência na leitura foi reduzida para ~600μs
no mesmo nível de tráfego de leitura. Todos esses testes foram executados sem Memcached e sem o
RocksDB block caching.
Para permitir que essa solução trabalhe com mais utilizações variadas, eles precisarão reduzir o
número de arquivos de SST que precisa ser verificado por consulta. Eles estão explorando opções
como a compactação no estilo universal do RocksDB ou a sua própria compactação personalizada,
onde poderiam controlar melhor a taxa de compactação, diminuindo assim a quantidade de dados
transferidos de e para o SSD.

 

Conclusão
Com isso, a Netflix está lançando a sua solução em fases para produção. Rend está atualmente em
produção servindo alguns dos seus mais importantes conjuntos de dados de personalização.
Números iniciais mostram as operações mais rápidas com maior confiabilidade, pois são menos
propensas a problemas temporários de rede. Além disso, estão no processo de implantação do
backend Mnemonic (L2) para seus usuários de adoção rápida. Enquanto ainda estão no processo de
ajustar o sistema, os resultados parecem promissores com potencial para economia substancial de
custos, enquanto continuam permitindo a facilidade de uso e velocidade que o EVCache sempre
proporcionou aos seus usuários.
Tem sido uma viagem e tanto para o deploy em produção, e ainda há muito a fazer: fazer o deploy
amplamente monitorar, otimizar, enxaguar e repetir. A nova arquitetura para EVCache Server é o
que permite a eles continuar a inovar de forma objetiva. Se você quiser ajudar a resolver este ou
outros grandes problemas semelhantes em arquitetura de nuvem, junte-se ao time da Netflix.***

 

Fonte: http://techblog.netflix.com/2016/05/application-data-caching-using-ssds.html

Deixe um comentário

Watch Dragon ball super