Resumo : Para cerca de 1 milhão de usuários ativos e 150 milhões de atividades armazenadas, eu simplifico:
- Use um banco de dados relacional para armazenar atividades exclusivas (1 registro por atividade / "coisa que aconteceu") Torne os registros o mais compactos possível. Estrutura para que você possa capturar rapidamente um lote de atividades por ID de atividade ou usando um conjunto de IDs de amigos com restrições de tempo.
- Publique os IDs de atividade no Redis sempre que um registro de atividade for criado, adicionando o ID a uma lista de "fluxo de atividades" para cada usuário amigo / assinante que deve ver a atividade.
Consulte Redis para obter o fluxo de atividades de qualquer usuário e, em seguida, obtenha os dados relacionados do banco de dados, conforme necessário. Volte a consultar o banco de dados por tempo se o usuário precisar navegar muito no tempo (se você oferecer isso)
Eu uso uma tabela antiga simples do MySQL para lidar com cerca de 15 milhões de atividades.
Parece algo como isto:
id
user_id (int)
activity_type (tinyint)
source_id (int)
parent_id (int)
parent_type (tinyint)
time (datetime but a smaller type like int would be better)
activity_type
informa o tipo de atividade, source_id
informa o registro ao qual a atividade está relacionada. Portanto, se o tipo de atividade significa "favorito adicionado", eu sei que o source_id se refere ao ID de um registro favorito.
Os parent_id
/ parent_type
são úteis para o meu aplicativo - eles me dizem a que a atividade está relacionada. Se um livro fosse favorito, parent_id / parent_type me diria que a atividade está relacionada a um livro (tipo) com uma determinada chave primária (id)
Eu indexo (user_id, time)
e procuro atividades que são user_id IN (...friends...) AND time > some-cutoff-point
. Abandonar o ID e escolher um índice em cluster diferente pode ser uma boa ideia - não experimentei isso.
Coisas bastante básicas, mas funcionam, são simples e são fáceis de trabalhar conforme as suas necessidades mudam. Além disso, se você não estiver usando o MySQL, poderá executar melhor em termos de índice.
Para acesso mais rápido às atividades mais recentes, experimentei o Redis . O Redis armazena todos os seus dados na memória, para que você não possa colocar todas as suas atividades nele, mas pode armazenar o suficiente para a maioria das telas mais comuns do seu site. Os 100 mais recentes para cada usuário ou algo parecido. Com Redis na mistura, pode funcionar assim:
- Crie seu registro de atividade do MySQL
- Para cada amigo do usuário que criou a atividade, envie o ID para sua lista de atividades no Redis.
- Aparar cada lista com os últimos X itens
O Redis é rápido e oferece uma maneira de canalizar comandos através de uma conexão - assim, enviar uma atividade para 1.000 amigos leva milissegundos.
Para uma explicação mais detalhada do que estou falando, consulte o exemplo do Redis no Twitter: http://redis.io/topics/twitter-clone
Atualização em fevereiro de 2011 Eu tenho 50 milhões de atividades ativas no momento e não mudei nada. Uma coisa legal de fazer algo semelhante a isso é que ele usa linhas pequenas e compactas. Estou planejando fazer algumas mudanças que envolvam muito mais atividades e mais consultas dessas atividades, e definitivamente utilizarei o Redis para manter as coisas rápidas. Estou usando o Redis em outras áreas e realmente funciona bem para certos tipos de problemas.
Atualização julho de 2014 Temos cerca de 700 mil usuários ativos mensais. Nos últimos dois anos, tenho usado o Redis (como descrito na lista com marcadores) para armazenar os últimos 1000 IDs de atividade para cada usuário. Geralmente, existem cerca de 100 milhões de registros de atividades no sistema e eles ainda estão armazenados no MySQL e ainda têm o mesmo layout. Esses registros nos permitem gastar menos memória Redis, eles servem como o registro dos dados da atividade e os usamos se os usuários precisarem voltar mais no tempo para encontrar algo.
Esta não foi uma solução inteligente ou especialmente interessante, mas me serviu bem.