18 pontos por xguru 2024-02-05 | 1 comentários | Compartilhar no WhatsApp
  • A Apple usa Cassandra e FoundationDB para o iCloud e o CloudKit
  • Esses bancos de dados armazenam bilhões de bancos de dados em uma arquitetura de multitenancy extrema

Lições reais que atravessam o tempo

  • Tanto a Meta quanto a Apple usam processamento assíncrono para viabilizar recursos para os usuários
  • As duas empresas usam uma arquitetura stateless para resolver problemas de escalabilidade
  • Isolam recursos logicamente para garantir confiabilidade e disponibilidade
  • Lidam com requisitos diversos de forma simples
  • Constroem camadas de abstração para melhorar a experiência do desenvolvedor
  • Conhecem seus usuários e definem cada camada, API e design com base nisso

Cassandra

  • Cassandra é um sistema de gerenciamento de banco de dados NoSQL de colunas largas
  • Foi originalmente desenvolvido no Facebook para o recurso de busca da caixa de entrada do Facebook
    • Curiosamente, a própria Meta substituiu a maior parte do uso de Cassandra pelo ZippyDB
  • O iCloud usa Cassandra em parte, e a Apple opera uma das maiores implantações de Cassandra do mundo
    • mais de 300 mil instâncias/nós
    • centenas de petabytes de dados
    • mais de 2 petabytes por cluster
    • milhões de consultas por segundo
    • milhares de aplicações
  • O Cassandra continua sendo ativamente aprimorado dentro da Apple
  • Porém, CloudKit + Cassandra esbarrou em limites de escalabilidade, o que levou à adoção do FoundationDB

FoundationDB

  • A Apple usa FoundationDB publicamente e o adquiriu em 2015
  • FoundationDB é um armazenamento transacional distribuído open source de chave-valor, projetado para lidar com dados em grande escala
    • adequado tanto para cargas de leitura/escrita quanto para cargas com muita escrita
  • A Apple usa amplamente o FoundationDB Record Layer no CloudKit
  • O FoundationDB Record Layer fornece uma API Java para armazenamento de dados estruturados
  • O Record Layer oferece suporte a multitenancy extrema

Por que usar o Record Layer sobre o FoundationDB

  • O FoundationDB lida com sistemas distribuídos e controle de concorrência.
  • O Record Layer funciona como um banco de dados relacional que torna o FoundationDB mais fácil de usar.
  • O CloudKit fica na camada mais alta, oferecendo recursos e APIs para desenvolvedores de aplicações.
  • Por meio do Record Layer, a Apple oferece suporte a multitenancy em larga escala
    • usado para multitenancy extrema, fornecendo um armazenamento de registros independente para cada usuário de cada aplicação
    • hospeda bilhões de bancos de dados independentes compartilhando milhares de esquemas

Como o CloudKit usa FoundationDB e o Record Layer

  • No CloudKit, as aplicações são representadas como 'contêineres lógicos' que seguem um esquema definido
    • esse esquema descreve de forma resumida os tipos de registro, campos e índices necessários para recuperação e consulta eficiente dos dados
    • as aplicações podem organizar dados em 'zonas' dentro do CloudKit, agrupando registros logicamente para permitir sincronização opcional com dispositivos clientes
  • Cada usuário recebe um subspace exclusivo dentro do FoundationDB, e é criado um armazenamento de registros para cada aplicação com a qual o usuário interage
    • em essência, o CloudKit gerencia um número gigantesco de bancos de dados lógicos equivalente ao número de usuários multiplicado pelo número de aplicações
    • cada banco de dados inclui seu próprio conjunto de registros, índices e metadados, chegando a bilhões de bancos de dados
  • Quando o CloudKit recebe uma solicitação de um dispositivo cliente, ele a encaminha por balanceamento de carga para um processo de serviço do CloudKit disponível
    • o processo interage com um armazenamento de registros específico do Record Layer para atender à solicitação
  • O CloudKit converte o esquema definido da aplicação em definições de metadados dentro do Record Layer, armazenadas em um repositório de metadados separado
    • esses metadados são complementados por campos de sistema específicos do CloudKit, que rastreiam criação e modificação de registros, além da zona em que o registro foi armazenado
    • para permitir acesso eficiente aos registros dentro de cada zona, a chave primária recebe como prefixo o nome da zona
    • junto com índices definidos pelo usuário, o CloudKit também mantém 'índices de sistema' para usos internos, como gerenciar cotas de armazenamento, acompanhando por exemplo o tamanho dos registros por tipo

O uso conjunto de FoundationDB e Record Layer resolve 4 problemas principais da Apple que só o Cassandra não conseguia resolver

1. Resolver o problema da busca de texto completo personalizada

  • O FoundationDB oferece suporte à busca de texto completo personalizada, permitindo que usuários acessem rapidamente seus próprios dados
  • Aproveitando a ordenação de chaves do FoundationDB, é possível pesquisar rapidamente o início do texto (correspondência por prefixo), além de executar buscas mais complexas sem overhead adicional, como busca por proximidade e busca por frase, encontrando palavras próximas entre si ou em uma ordem específica
  • Em sistemas de busca tradicionais, muitas vezes é preciso executar processos extras em background para manter os índices de busca atualizados, mas o sistema da Apple faz tudo em tempo real, então o índice é atualizado imediatamente sempre que os dados mudam, sem etapas adicionais

2. Resolver o problema de zonas com alta concorrência

  • O CloudKit usa FoundationDB para lidar de forma fluida com muitas atualizações simultâneas
  • Antes, ao usar Cassandra, o CloudKit dependia de um índice especial que rastreava mudanças em cada zona para sincronizar dados entre vários dispositivos
    • quando um dispositivo precisava atualizar dados, verificava esse índice para ver o que havia de novo
    • porém, quando várias atualizações aconteciam ao mesmo tempo, isso podia gerar conflitos
  • Com FoundationDB, o CloudKit usa um tipo especial de índice que acompanha a ordem exata de cada mudança sem causar conflitos
    • isso é feito atribuindo uma 'versão' única a cada alteração, e o CloudKit verifica essas versões quando precisa sincronizar para descobrir quais atualizações o dispositivo perdeu
  • Quando o CloudKit precisa mover dados entre vários clusters de armazenamento para distribuir melhor a carga, a situação fica mais complicada, porque os números de versão de cada cluster não coincidem
    • para resolver isso, o CloudKit atribui a cada dado de usuário uma 'contagem de migrações' (chamada de 'incarnation') que aumenta sempre que os dados são movidos para um novo cluster
    • cada atualização de registro inclui o número atual de 'incarnation' do usuário, então, mesmo após a migração, o CloudKit consegue determinar a ordem correta das atualizações verificando tanto a incarnation quanto o número de versão
  • Ao migrar para o novo sistema, o CloudKit enfrentou o problema de lidar com dados antigos que não tinham esses números de versão
    • mas superou isso de forma inteligente com um recurso especial que ordena atualizações antigas feitas pelo sistema anterior antes das atualizações do novo sistema
    • isso evitou a necessidade de mudanças complexas nas aplicações ou de manter código legado
    • para preservar a ordem correta do histórico, considera os valores de incarnation, versão e contagem de atualizações antigas

3. Resolver o problema de consultas com alta latência

  • O FoundationDB foi projetado para alta concorrência, e não para baixa latência. Ou seja, consegue lidar com muitas operações ao mesmo tempo em vez de focar na velocidade de cada operação individualmente
  • Para aproveitar isso ao máximo, o Record Layer executa muitas operações de forma assíncrona
    • colocando tarefas em fila para conclusão futura e permitindo executar outras tarefas nesse meio-tempo
    • essa abordagem ajuda a encobrir a latência que pode surgir durante essas operações
  • Porém, a ferramenta que o FoundationDB usa para se comunicar com o banco de dados foi projetada para usar uma única thread para rede, processando uma tarefa por vez
    • em versões anteriores, essa configuração causava congestionamento porque todas as operações precisavam esperar sua vez nessa thread de rede
    • como o Record Layer usava essa abordagem de thread única, isso criava um gargalo
  • Para melhorar isso, a Apple reduziu a carga de trabalho dessa thread de rede
    • agora o sistema consegue trabalhar com o banco de dados em vários aspectos ao mesmo tempo, sem formar filas, tornando operações complexas mais rápidas
    • isso mascara a latência ou a lentidão percebida, porque o sistema não precisa esperar uma operação terminar antes de iniciar outra

4. Resolver o problema de transações em conflito

  • No FoundationDB, ocorre um 'conflito de transação' quando uma transação lê uma chave específica enquanto outra transação modifica essa mesma chave
    • o FoundationDB oferece controle sobre os conjuntos de chaves que podem gerar esses conflitos em leituras ou escritas, permitindo gerenciá-los com precisão
  • Uma forma comum de evitar conflitos desnecessários é fazer um tipo especial de leitura que não gera conflito, a leitura de 'snapshot', sobre várias chaves
    • se essa leitura encontrar uma chave importante, a transação marca apenas a chave específica com potencial de conflito, e não o intervalo inteiro
    • assim, a transação só é afetada por mudanças que realmente importam para o resultado
  • O Record Layer usa essa estratégia para gerenciar com eficiência uma estrutura chamada skip list, que faz parte do sistema de índice de ranking
    • porém, definir manualmente esses intervalos de conflito pode ser complicado e, especialmente quando misturado à lógica principal da aplicação, pode levar a bugs difíceis de identificar
    • por isso, em sistemas construídos sobre o FoundationDB, é recomendável criar ferramentas de nível mais alto, como índices customizados, para lidar com esses padrões
    • essa abordagem ajuda a evitar situações em que a responsabilidade por flexibilizar as regras de conflito fica com cada aplicação cliente, o que pode causar erros e inconsistências

1 comentários

 
xguru 2024-02-05

Comentários do Hacker News

  • Um usuário do Hacker News compartilhou percepções sobre a diferença entre bancos de dados e sistemas de arquivos quando trabalhava na Apple. Ele mencionou que bancos de dados e sistemas de arquivos desempenham fundamentalmente a mesma função e são otimizações para resolver problemas específicos. Como exemplo, o iCloud mostra uma forma de definir um sistema de arquivos com base em um banco de dados. Esse usuário também compartilhou sua experiência usando Cassandra para armazenar vídeos.

  • Outro usuário mencionou a experiência de ter construído um sistema de catálogo transacional em uma empresa anterior usando FoundationDB e RecordLayer. O sistema era muito eficaz, e usar gRPC e Protobuf parecia natural. No entanto, apontou como desvantagem a alta barreira de entrada para operar o FoundationDB em grande escala.

  • Um usuário avaliou que o recurso de sincronização do Apple Notes lida melhor com conflitos do que aplicativos de notas baseados em Markdown. Por isso, mencionou que acabou migrando para o Apple Notes.

  • Foram mencionadas postagens anteriores sobre o FoundationDB. Isso inclui links sobre o armazenamento distribuído de chave-valor do FoundationDB, a Record Layer, a aquisição pela Apple, além do funcionamento e das características do FoundationDB.

  • Foi mencionado um ponto interessante sobre a arquitetura de softwares nativos de desktop que estão migrando gradualmente para armazenamento e colaboração baseados em nuvem. É importante lidar bem com mudanças de esquema e migrações de versão, e isso acontece em grande escala sem intervenção de administradores.

  • Um usuário gostaria que o iCloud pudesse armazenar backups do Time Machine.

  • Como o FoundationDB é baseado em SQLite, foi levantada uma curiosidade sobre a possibilidade de aplicar o mecanismo HCTree ao FoundationDB. O HCTree tem potencial para melhorar em 10 vezes o desempenho de leitura e escrita do SQLite.

  • Houve reclamações sobre como o iCloud gerencia os arquivos dos usuários. Às vezes, torna-se um problema quando o iCloud move automaticamente para a nuvem arquivos, aplicativos e fotos usados recentemente para liberar espaço.

  • Um usuário relembrou um sistema de relatórios chamado Hyperion, que usou quando trabalhava em um banco no passado. Esse sistema criava um novo banco de dados para cada relatório, o que na época parecia estranho, mas hoje, pensando bem, ele mencionou que era uma abordagem à frente do seu tempo.