29 pontos por xguru 2022-08-17 | 3 comentários | Compartilhar no WhatsApp
  • Operava um cluster de banco de dados NoSQL (ScyllaDB) que processa 2 milhões de mensagens por segundo
  • O fator que mais impactava o desempenho do banco era a latência do hardware de disco físico
    → Em níveis baixos de consultas isso não importava, mas ao ultrapassar certo ponto, apenas o tempo de leitura de 1~2 ms já criava fila de espera no disco, causando timeout nas próprias consultas
  • A latência de disco normalmente é medida em microssegundos, então por que uma operação de disco levava 1~2 ms?
  • O Discord opera a maior parte do hardware no Google Cloud
    • Há suporte a SSD local baseado em NVMe, mas em testes próprios foram encontrados problemas de estabilidade, então não era confortável usá-lo como armazenamento de dados críticos
    • O Persistent Disk pode ser conectado e desconectado do servidor em tempo real, redimensionado sem downtime, permite criar snapshots a qualquer momento e foi projetado com replicação por padrão
      → O problema é que ele não fica conectado diretamente ao servidor, e sim pela rede
  • Por menor que seja a latência de uma conexão de rede local, ela não fica abaixo de PCI/SATA
    → Rede: 1~2 ms, disco conectado diretamente: 0,5 ms
  • Com SSD local, se houver um problema de hardware como nos HDDs, os dados daquele disco são perdidos; e se houver problema no próprio host, nem snapshots são possíveis, podendo resultar em perda total dos dados
    → Por isso o Discord não usou Local SSD e passou a usar Persistent Disk

Análise do problema

  • O ideal seria ter um dispositivo de armazenamento que reunisse apenas as vantagens do SSD local e do Persistent Disk, mas isso não existe. E se fosse possível aproveitar pelo menos parte das vantagens?
  • Para o Discord, a latência de escrita não era o problema. O que afetava o desempenho era a "latência de leitura"
  • "Redimensionamento de disco sem downtime" não era um requisito essencial. O tamanho podia ser previsto com antecedência
  • Os requisitos finais eram:
    • Continuar no GCP
    • Usar snapshots point-in-time para backup dos dados
    • Priorizar acima de tudo a minimização da latência de leitura
    • Não sacrificar a garantia de uptime do banco de dados existente
  • Parecia bom usar o Local SSD do GCP para leitura e o Persistent Disk para escrita
    → Seria possível criar esse tipo de superdisco no nível de software?

Criando o Super-Disk

  • O requisito, na prática, era um cache write-through. Usar o SSD local do GCP como cache e o PD como camada de armazenamento
  • Como os servidores de banco usavam Ubuntu, era possível aplicar cache em nível de disco no kernel Linux (dm-cache, lvm-cache, bcache etc.)
  • Mas, nos testes, quando surgiam bad sectors no disco de cache, toda a operação de leitura falhava
    • Quando aparece um bad sector, seria preciso reler da camada de armazenamento e sobrescrever, mas as soluções de cache de disco avaliadas não tinham essa função
    • Quando havia bad sectors, o banco de dados acabava sendo desligado por problemas de integridade dos dados
  • Então foi adicionado outro requisito: "precisa sobreviver mesmo que haja bad sectors no SSD local"
  • Por isso, passaram a analisar o md do Linux
    • O md permite criar RAID via software
    • Espelhar SSD e PD não resolvia o problema, porque mais da metade das leituras acabaria vindo do PD
    • O md tem a opção write-mostly, que não existe no RAID tradicional
      • Se um disco específico for definido como write-mostly, ele é excluído das leituras normais e só é usado para leitura quando não há outra opção. É "útil para dispositivos conectados lentamente"
      • Ou seja, ao agrupar SSD e PD em RAID1 e configurar o PD como write-mostly, dava para atender aos requisitos
  • O último problema restante era que o Local SSD do GCP tem tamanho fixo de 375 GB
  • Para certas aplicações, o Discord precisava de mais de 1 TB por instância de banco
  • Então decidiram agrupar vários SSDs em RAID0
  • A configuração final ficou assim:
    • 4 Local SSDs agrupados em RAID0 formando o md0
    • md0 e o Persistent Disk agrupados em RAID1 formando o md1

Desempenho do banco de dados

  • O resultado foi exatamente o esperado
  • Mesmo nos picos, as operações de disco não se acumulavam em fila, e a latência das consultas não mudava
  • O ganho de desempenho aumentou a quantidade de consultas processadas por servidor
  • Quem já usou RAID pode se perguntar se isso "simplesmente funciona", mas na prática aconteceram várias coisas, e o restante será apresentado em detalhes separadamente

3 comentários

 
eajrezz 2022-08-19

Antes, eu já achava impressionante o nível geek da Discord por, insatisfeita com a performance do Golang, chegar ao ponto de escrever até servidores em Rust.

 
psyrenpark 2022-08-17

Parece uma daquelas situações em que se tenta resolver um problema pequeno com uma solução exagerada.

 
xguru 2022-08-17

No HN, há também quem diga: isso não é simplesmente um problema do GCP?
https://news.ycombinator.com/item?id=32474093
Acho que vale a pena pelo menos saber que esse tipo de tentativa também é possível.