TL; DR:
Eles usam uma arquitetura de pilha com gráficos em cache para tudo acima da parte inferior do MySQL da pilha.
Resposta longa:
Eu mesmo fiz algumas pesquisas porque estava curioso para saber como eles lidam com sua enorme quantidade de dados e os pesquisam rapidamente. Vi pessoas reclamando sobre scripts de redes sociais personalizados ficando lentos quando a base de usuários cresce. Depois que fiz alguns testes comparativos com apenas 10.000 usuários e 2,5 milhões de conexões de amigos - nem mesmo tentando me preocupar com permissões de grupos, curtidas e publicações no mural -, rapidamente percebi que essa abordagem é falha. Por isso, passei algum tempo pesquisando na Web sobre como fazê-lo melhor e me deparei com este artigo oficial do Facebook:
Eu realmente recomendo que você assista à apresentação do primeiro link acima antes de continuar lendo. É provavelmente a melhor explicação de como o FB funciona nos bastidores que você pode encontrar.
O vídeo e o artigo mostram algumas coisas:
- Eles estão usando o MySQL na parte inferior de sua pilha
- Acima do banco de dados SQL, há a camada TAO que contém pelo menos dois níveis de armazenamento em cache e usa gráficos para descrever as conexões.
- Não consegui encontrar nada sobre qual software / banco de dados eles realmente usam para seus gráficos em cache
Vamos dar uma olhada nisso, as conexões de amigos estão no canto superior esquerdo:
Bem, este é um gráfico. :) Não diz como construí-lo no SQL, existem várias maneiras de fazê-lo, mas este site possui uma boa quantidade de abordagens diferentes. Atenção: Considere que um banco de dados relacional é o que é: pensa-se armazenar dados normalizados, não uma estrutura de gráfico. Portanto, não terá um desempenho tão bom quanto um banco de dados gráfico especializado.
Considere também que você precisa fazer consultas mais complexas do que apenas amigos de amigos, por exemplo, quando deseja filtrar todos os locais em torno de uma determinada coordenada de que você e seus amigos gostam. Um gráfico é a solução perfeita aqui.
Não sei dizer como construí-lo para que ele tenha um bom desempenho, mas exige claramente algumas tentativas, erros e comparações.
Aqui está o meu teste decepcionante para apenas encontrar amigos de amigos:
Esquema do banco de dados:
CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`friend_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
Consulta de amigos de amigos:
(
select friend_id
from friends
where user_id = 1
) union (
select distinct ff.friend_id
from
friends f
join friends ff on ff.user_id = f.friend_id
where f.user_id = 1
)
Eu realmente recomendo que você crie alguns dados de amostra com pelo menos 10k registros de usuários e cada um deles tenha pelo menos 250 conexões de amigos e execute essa consulta. Na minha máquina (i7 4770k, SSD, 16gb RAM), o resultado foi ~ 0,18 segundos para essa consulta. Talvez possa ser otimizado, não sou um gênio do banco de dados (sugestões são bem-vindas). No entanto, se isso for linear, você já terá 1,8 segundos para apenas 100 mil usuários, 18 segundos para 1 milhão de usuários.
Isso ainda pode parecer bom para ~ 100k usuários, mas considere que você acabou de buscar amigos de amigos e não fez nenhuma consulta mais complexa como " exibir apenas postagens de amigos de amigos + fazer a verificação de permissão se sou permitido ou NÃO para ver alguns deles + faça uma subconsulta para verificar se eu gostei de algum deles ". Você deseja deixar o banco de dados fazer a verificação se você gostou de uma postagem ou não, ou terá que fazer isso no código. Considere também que essa não é a única consulta executada e que você tem mais de um usuário ativo ao mesmo tempo em um site mais ou menos popular.
Acho que minha resposta responde à pergunta de como o Facebook projetou o relacionamento de amigos muito bem, mas lamento não poder dizer como implementá-lo de uma maneira que funcione rapidamente. Implementar uma rede social é fácil, mas garantir que ela tenha um bom desempenho claramente não é - IMHO.
Comecei a experimentar o OrientDB para fazer consultas de gráficos e mapear minhas bordas para o banco de dados SQL subjacente. Se eu fizer isso, escreverei um artigo sobre isso.