Orthrus: detecção eficiente e oportuna de corrupção silenciosa de dados de usuário na nuvem com validação de computação adaptável a recursos
Título original: Orthrus: Efficient and Timely Detection of Silent User Data Corruption in the Cloud with Resource-Adaptive Computation Validation
PublicadoProceedings of the ACM SIGOPS 31st Symposium on Operating Systems Principles
Saiu em uma revista, congresso ou livro, que normalmente avaliam o trabalho antes de aceitar. Mesmo assim, um único estudo nunca é a palavra final.
Resumo
Este paper não tem resumo disponível.
Análise de pesquisa
Escrita pelo Kurz, não pelos autores do paper. O resumo acima é dos próprios autores.
- Última revisão
- Versão
- 1.0
Visão geral
Na escala da nuvem, os processadores deixaram de ser totalmente confiáveis. Estudos do Google (que chama esses cores de "mercurial"), da Meta e da Alibaba descrevem cores que passam a calcular errado depois de instalados, muitas vezes um core de cada vez, sem derrubar nada nem acionar nenhum aviso de hardware. O artigo cita um teste da Alibaba com mais de um milhão de processadores em que 3,61 a cada 10.000 apresentaram erros capazes de causar corrupção silenciosa de dados (SDC, de silent data corruption). Uma SDC que muda o que um banco de dados devolve pode violar um SLA, o que, segundo os autores, é muito pior do que uma queda.
Este artigo do SOSP 2025 (realizado em Seul), da University of Chinese Academy of Sciences, UCLA, UC Berkeley, Tsinghua University e Peking University, pergunta como pegar essa corrupção online e de forma barata o bastante para produção. O teste offline periódico de CPUs, por exemplo a cada três meses, encontra cores defeituosos, mas não os dados que eles já corromperam. Os autores dizem que a validação baseada em replicação (RBV, de replication-based validation), que roda uma réplica completa, exige mais de 100% de CPU e memória extras, e que a validação em nível de instrução (ILV, de instruction-level validation) exige hardware especial e deixa a execução 50 vezes mais lenta.
Termos para manter separados: o caminho de controle (rede, parsing, despacho) move os dados do usuário sem alterá-los, enquanto o caminho de dados contém operadores como get, set, map e reduce. Uma closure é um operador anotado do caminho de dados, APP é a sua execução original e VAL é a sua reexecução em outro core. Cobertura é a fração das corrupções injetadas que são detectadas, e um erro mascarado é aquele que nunca altera um resultado.
Vale conhecer antes: a ideia de máquina de estados replicada por trás da RBV, que a seção de trabalhos relacionados do artigo ancora no Paxos e no Raft e ilustra com bancos replicados como o Spanner. O artigo cita os três, mas só toma emprestado o padrão de replicação, não os protocolos. LLVM IR e análise de escape ajudam na parte do compilador.
Contribuição
- Uma divisão que barateia a validação. No Memcached, o caminho de controle é mais de 20× maior que o caminho de dados, e apenas quatro arquivos (assoc.c, hash.c, item.c, cache.c) manipulam dados do usuário. O Orthrus reexecuta apenas os operadores do caminho de dados, em vez do programa inteiro, como faz a RBV.
- Duas anotações e um compilador. Os desenvolvedores marcam operadores com
closuree estruturas de dados comuser-data. Uma passada do LLVM descobre as entradas e saídas de cada closure, coloca as alocações de dados do usuário em memória versionada (OrthrusNew) e direciona os acessos porOrthrusPtr, usando inferência de tipos e análise de escape. As closures precisam ser single-threaded, e objetos que não escapam ficam em um heap privado. - Memória versionada e logs de closure. A aplicação e o validador são processos separados, com heaps privados e um espaço de dados do usuário compartilhado. Cada
storecria uma nova versão fora do lugar, então o validador consegue reexecutar uma closure exatamente sobre o estado de memória que a aplicação viu. Um log de closure registra entradas, saídas, versões escritas e resultados de chamadas de sistema, que são reproduzidos em vez de reexecutados. O validador escreve apenas no próprio heap e compara as saídas com um==sobrecarregável ou bit a bit. - Validação fora de ordem em cores ociosos. Os logs vão para filas por core, e o validador roda em threads de usuário do Shenango, em cores ociosos do mesmo nó NUMA, mas nunca no core da aplicação, porque as ALUs, FPUs e unidades vetoriais da Intel são privadas de cada core. Se a latência de validação recente de uma closure (últimos oito logs) passa de um limite, como 50% acima da média, o scheduler inicia outra thread de validação que assume metade das filas dela, e o work stealing equilibra a carga.
- Amostragem adaptativa aos recursos. A validação começa com todas as closures em baixa prioridade e reduz a taxa de amostragem em degraus quando o atraso passa de um limite. A prioridade vai para closures não validadas recentemente, rastreadas por par (closure, chamador), e para closures que o compilador marca como usuárias de instruções de ponto flutuante ou vetoriais, já que estudos anteriores ligam os erros a essas instruções e a trechos específicos de código.
- Checksums para o caminho de controle. Cada versão de dado carrega um CRC de 16 bits, criado em
OrthrusNewoustoree conferido no primeiroloaddepois que o dado atravessa o caminho de controle. Os autores dizem que ele custa algumas dezenas de ciclos de CPU por objeto. - Liberação de versões sem contagem de referências. Uma versão fica visível da sua criação até a versão seguinte ou um delete, e uma closure fica ativa da execução até o fim da validação. As versões cuja janela fechou antes de a closure pendente mais antiga começar são liberadas em lote, uma aproximação que evita as operações atômicas da contagem de referências.
- Modo seguro. Por padrão, os resultados são devolvidos sem esperar a validação. Um modo estrito opcional retém os resultados até que a closure correspondente seja validada.
Metodologia
O Orthrus é escrito em C/C++ sobre o LLVM. Os experimentos rodam em três servidores, cada um com duas CPUs Intel Xeon Gold 6342 e InfiniBand ConnectX-5 de 100 Gbps, com Turbo Boost, C-states e escalonamento de frequência desativados. Quatro aplicações foram anotadas: Memcached (cinco closures, um trace enviesado do CacheLib com 150 milhões de operações, 32 threads de cliente contra 4 threads de servidor), Masstree (200 milhões de operações da carga ALEX, metade consultas por intervalo e metade atualizações, 4 cores de servidor e 16 de cliente), a camada em memória de uma LSM-tree (50 milhões de escritas aleatórias, um teste de estresse intencional) e Phoenix (contagem de palavras sobre 15 GB de dados do WMT, 16 cores). Os autores dizem que portar essas aplicações alterou menos de 20 linhas.
As bases de comparação são as aplicações originais (vanilla) e a RBV, que os autores montaram como uma réplica em um servidor separado, com tantos cores quanto a aplicação, recebendo requisições em lote na mesma ordem e interrompendo o primário a qualquer divergência. A ILV fica de fora por suas exigências de hardware e seu overhead. O Orthrus usou dois cores de validação nos experimentos de overhead e latência e variou esse número na cobertura.
A cobertura foi medida por injeção de falhas feita pelo compilador (uma passada do LLVM em nível de máquina, construída sobre o REFINE), com bit flips, stuck-at-0, stuck-at-1 e falhas do tipo no-op, nos caminhos de controle e de dados, sobre os quatro tipos de recurso vulnerável relatados pela Alibaba: lógica aritmética, vetorial, ponto flutuante e coerência de cache. Cobertura é o número de corrupções detectadas dividido pelo número das que ocorreram, comparada com a RBV e com a amostragem aleatória. Um segundo experimento fixou dois cores e permitiu de 5% a 40% de memória extra acima do consumo do vanilla.
Resultados
Estes são os resultados relatados pelos autores.
- Overhead. Com dois cores de validação, o Orthrus custa em média 4% de tempo de execução e 25% de memória, contra overheads de 2,0× e 2,1× da RBV. A introdução resume isso como 1,9× mais rápido que a RBV.
- Por aplicação. O Memcached perde 4,4% de throughput em relação ao vanilla e é 1,6× mais rápido que a RBV, que gasta 43% da sua CPU com comunicação. O Masstree fica comparável ao vanilla enquanto a RBV fica 65% abaixo do Orthrus, uma diferença de 2,9×. O LSMTree mantém 95% do throughput do vanilla com 34% de memória extra, e a RBV fica 54% atrás dele. O Phoenix acrescenta menos de 2% de tempo e 2,6% de memória, enquanto a RBV perde 51% do throughput e relata um overhead de memória de 2,1×.
- Custos do gerenciamento de dados. O
OrthrusPtracrescenta em média 7% de memória e 3% de tempo de execução, e os checksums custam menos de 1%. Com um core de validação, o uso de memória cai em média 36%, porque os logs são validados ou descartados mais cedo. - Oportunidade da detecção. A latência média de validação é de 1,6 µs no Memcached, 22,6 µs no Masstree, 7,7 µs no LSMTree e 234 ms no Phoenix, cujas operações levam até 240 ms. A RBV tem média de 90 µs no Memcached (56× maior) e 513 ms no Phoenix, e é 21× pior no Masstree e 8× no LSMTree. O Memcached com RBV também mostra latência de requisição no percentil 95 até 1000× a do Orthrus.
- Cobertura com cores em abundância. Com tantos cores de validação quanto cores de aplicação, o Orthrus detecta 97,2%, 97,6%, 97,6% e 98,9% das SDCs injetadas aritméticas, de ponto flutuante, vetoriais e de cache, contra 98,3%, 99,5%, 99,5% e 99,8% da RBV. Todos os casos, menos três, que a RBV pegou e o Orthrus perdeu eram erros no caminho de controle, e os três eram erros em chamadas de sistema (um em um write, dois em operações de mutex).
- Cobertura com poucos cores. O resumo do artigo relata 87%, 91% e 96% com um, dois e quatro cores de validação. O texto dá 86,7% em média com um core, o que é 1,41× a amostragem aleatória. O Memcached não muda, o Phoenix é o mais baixo, com 78,2% (16 threads, comparação pesada em memória), e o Masstree perde só 8,6% ao ir de quatro cores para um.
- Limites de memória. Com dois cores e a memória extra limitada, o Phoenix se mantém estável, a detecção do Masstree cai de forma constante conforme a memória diminui (atualizações da árvore e closures não validadas atrasam a liberação), e o Memcached é afetado apenas de leve.
Análise crítica
O artigo é franco sobre ser uma ferramenta de melhor esforço, não uma garantia, e admite o seguinte.
- Pontos cegos por construção. Erros mascarados são invisíveis, o que os autores aceitam porque não mudam resultados. Chamadas de sistema, locks e outras chamadas não determinísticas são reproduzidas do log, não validadas, embora os autores encontrem apenas 0,04% das instruções executadas nelas. Um erro que faça o caminho de controle chamar o operador errado escapa dos checksums, dois cores falhando de modo idêntico passariam despercebidos, e a corrupção de objetos temporários que não escapam passa sem ser notada, a menos que chegue à memória versionada.
- A amostragem pode pular erros. A cobertura depende dos cores que sobram, e funções não escolhidas para validação não são conferidas. Os autores apontam a RBV quando há recursos em abundância e o teste offline se o objetivo for apenas achar CPUs defeituosas.
- Custos deixados em aberto. Os autores citam um pool allocator dedicado aos metadados de versão e anotações mais grossas como trabalho futuro para reduzir os custos de 7% e 3%, e chamam de irreal a carga do LSMTree só com escritas.
Os pontos a seguir são uma leitura das evidências, não afirmações do artigo.
- As falhas são emuladas, e os detalhes são escassos. Bit flips, stuck-at e no-ops injetados pelo compilador fazem as vezes de cores defeituosos reais, que o apêndice diz não estarem disponíveis no mercado. O texto descreve a Tabela 2 como erros injetados, mas a coluna se chama "Total SDCs" (cerca de 2.500 casos pela minha soma), então não fica claro se os desfechos mascarados e fail-stop foram filtrados antes. Não há repetições nem sementes relatadas, e o texto que li não diz como uma falha plantada em uma closure fica fora da reexecução do mesmo código pelo validador. O artigo remete os detalhes da injeção a um documento suplementar.
- Os números de destaque diferem entre as seções. O resumo diz que o overhead é de 2% a 6%, o corpo diz cerca de 4%. O overhead de memória é de cerca de 20% na seção de liberação de memória, 25% na avaliação e até 35% no Masstree. O texto dá 97,2% para o Orthrus nas falhas aritméticas, mas as contagens da Tabela 2 somam 96,5%. O texto dos limites de memória do Phoenix relata média de 91% e depois uma "pequena queda" para 92,7%, o que parece um erro de digitação.
- A afirmação sobre latência é mais forte que os dados. A introdução cita 40 µs e "três ordens de magnitude" abaixo da RBV, e a seção 4.3 diz "duas ou três ordens". As médias que o texto dá são 56×, 21× e 8× nas três aplicações sensíveis à latência e cerca de 2× no Phoenix (513 ms contra 234 ms). Só a latência de cauda de requisição do Memcached, outra métrica, chega a 1000×.
- Por padrão, a detecção vem depois do fato. A seção de objetivos diz que a aplicação é abortada quando uma SDC é achada, para que o dado corrompido não seja devolvido, mas por padrão os resultados saem sem esperar a validação. O modo seguro estrito fecha a brecha, porém nunca é medido, só defendido a partir dos custos pequenos de validação, e o Phoenix só revela resultados no fim, com latência média de validação de 234 ms. As closures descartadas pela amostragem nem chegam a ter uma latência.
- A base RBV e as cargas são estreitas. A RBV é uma montagem dos próprios autores, que atribuem suas perdas à serialização, à reprodução da ordem e à comparação de estruturas complexas, então não se testou quanto uma réplica construída de outro jeito reduziria a diferença. As quatro aplicações são cargas de chave-valor ou em lote com poucas closures, o Memcached é dominado por leituras, o teste da LSM-tree cobre só a camada em memória, e as closures precisam ser single-threaded. Os jobs do tipo Spark usados para criticar a RBV não são avaliados.
- A amostragem se apoia em premissas emprestadas, em uma só plataforma. Dar menos peso a closures validadas recentemente pressupõe que os erros são reproduzíveis e ligados ao código, premissa tirada de estudos anteriores. O ganho de 1,41× sobre a amostragem aleatória é medido com falhas injetadas, então depende de quão bem elas imitam defeitos reais, possivelmente dependentes dos dados. A política de scheduling depende das unidades de execução privadas de cada core das CPUs Intel, e só um tipo de servidor é usado.
Pesquisas futuras
- Um pool allocator para os metadados de versionamento e anotações de dados mais grossas, que os autores deixam como trabalho futuro, para reduzir os custos de tempo de execução e de memória.
- Testes com cores defeituosos reais ou traces de erros em produção, incluindo se pular closures validadas recentemente se sustenta para falhas dependentes dos dados.
- Fechar as brechas do caminho de controle e das chamadas de sistema, por exemplo com verificações no ponto em que o caminho de controle escolhe o operador.
- Medir o modo seguro estrito de ponta a ponta e estender o Orthrus a operadores multithread e a hardware não Intel, onde a política de scheduling configurável precisaria de novas regras de posicionamento.
Discussão · 0
Entre para participar da discussãoNenhum post ainda. Seja o primeiro a iniciar a discussão.