o problema
Uma consulta ao Google lê centenas de megabytes e consome dezenas de bilhões de ciclos de CPU. Multiplique isso por milhares de consultas por segundo no pico e a infraestrutura necessária fica comparável às maiores instalações de supercomputação da época. Os documentos brutos somavam dezenas de terabytes não comprimidos, e o índice invertido derivado deles já ocupava muitos terabytes por conta própria.
A resposta padrão em 2003 para carga desse porte era comprar máquinas grandes: multiprocessadores de memória compartilhada, fonte redundante, RAID, disco SCSI, interconexão de alta banda. Cada item dessa lista existe para reduzir a chance de a máquina cair, e cada um cobra caro por isso. O paper coloca a conta na mesa. Um rack de 88 servidores dual-Xeon de 2 GHz custava cerca de US$ 278.000 no fim de 2002 e entregava 176 CPUs, 176 Gbytes de RAM e 7 Tbytes de disco. Um servidor x86 de topo com 8 CPUs, 64 Gbytes de RAM e 8 Tbytes de disco custava cerca de US$ 758.000. Três vezes o preço para vinte e duas vezes menos CPU.
a ideia
Se a aplicação tolera perder uma máquina, você não precisa comprar máquinas que não caem. O Google trocou confiabilidade de hardware por confiabilidade de software: replica cada serviço interno em muitos servidores, detecta a falha automaticamente e desvia o tráfego. A réplica já estava lá de qualquer jeito, para dar capacidade — a tolerância a falha vem quase de graça em cima dela.
O segundo movimento é sobre o que se otimiza. O sistema não persegue o menor tempo de resposta de um servidor, e sim o maior throughput agregado do conjunto; a latência de uma consulta individual se resolve dividindo o trabalho entre mais CPUs e mais discos. Daí a regra de compra: escolher a geração de CPU com melhor performance por dólar, não a com melhor performance absoluta.
como funciona
O navegador resolve www.google.com por DNS, e um balanceamento baseado em DNS escolhe um dos clusters distribuídos pelo mundo levando em conta proximidade geográfica e capacidade disponível. A partir daí o processamento é inteiro local àquele cluster, o que também protege contra a perda de um data center inteiro por terremoto ou falta de energia. Dentro do cluster, um balanceador de hardware distribui a requisição entre os Google Web Servers, e o GWS coordena a execução e monta o HTML final.
A execução tem duas fases. Na primeira, os index servers consultam o índice invertido que mapeia cada palavra para sua hit list, intersectam as listas e calculam o score de relevância de cada documento. O índice é dividido em shards, cada um com um subconjunto aleatório dos documentos; um pool de máquinas atende cada shard, e um balanceador intermediário escolhe a réplica. Se uma réplica cai, o balanceador para de usá-la e a capacidade do sistema diminui na proporção daquela máquina — mas o índice continua inteiro disponível. O resultado é uma lista ordenada de docids.
Na segunda fase, os document servers pegam esses docids e produzem título, URL e o snippet com a palavra em contexto, lendo o documento do disco. Mesma receita: shards aleatórios, réplicas por shard, balanceador na frente. Isso exige uma cópia online e de baixa latência da web inteira; com a replicação, o Google guardava dezenas de cópias da web entre seus clusters. Em paralelo, o GWS dispara ainda o corretor ortográfico e o servidor de anúncios.
O hardware é banal de propósito. Racks com 40 a 80 servidores x86 montados dos dois lados, de Celeron 533 MHz a Pentium III dual de 1,4 GHz, discos IDE de 80 Gbytes, switch Ethernet de 100 Mbps por lado com uplink gigabit para o switch central.
o que isso custou
A medição do index server mostra um workload que a microarquitetura da época servia mal: CPI de 1,1 num Pentium III capaz de emitir três instruções por ciclo, 5,0% de branch mispredict, percurso de estruturas dinâmicas e fluxo de controle dependente de dados. O mesmo programa no Pentium 4 tem quase o dobro do CPI. Não há ILP explorável ali, e os autores dizem sem rodeios que execução especulativa fora de ordem já passou do ponto de retorno decrescente para esse tipo de código. A saída apontada é paralelismo de thread: um Xeon com SMT dual-context deu mais de 30% de ganho, e CMP com núcleos simples e in-order parecia mais promissor ainda.
O limite mais duro é elétrico. Um servidor dual Pentium III de 1,4 GHz puxa cerca de 90 W DC, 120 W AC depois da fonte ATX, o que dá algo como 10 kW por rack e uma densidade de 400 W/ft² — com processadores mais rápidos, mais de 700 W/ft². Data centers comerciais entregavam entre 70 e 150 W/ft². Empacotar mais servidores por rack, portanto, tem utilidade prática limitada enquanto os racks morarem em data centers padrão. E servidor econômico não resolve sozinho: energia mais refrigeração custavam US$ 1.500 por mês contra US$ 7.700 de depreciação, então um servidor de baixo consumo que seja mais caro perde a conta.
Há um custo escondido no modelo também. Máquinas com mais de três anos ficam lentas demais para conviver no mesmo cluster sem estragar a distribuição de carga, o que encurta a amortização e faz o preço do equipamento pesar ainda mais. E a arquitetura só é honesta porque a aplicação é quase só leitura e quase sem estado — os próprios autores delimitam: ela serve para quem tem paralelismo de requisição e servidores sem estado privado.
onde isso aparece hoje
Este é o paper que descreve a máquina onde rodava o buscador de The Anatomy of a Large-Scale Hypertextual Web Search Engine. A premissa que ele estabelece — hardware barato que falha o tempo todo, confiabilidade construída acima dele — vira o pressuposto explícito de The Google File System e de MapReduce nos anos seguintes, e o problema de administrar essa frota acaba em Borg. A observação de que a capacidade cai em proporção à máquina perdida, sem interromper o serviço, reaparece com outro nome em The Tail at Scale, de dois dos mesmos autores.