Comment mettre en œuvre le flux d'activités dans un réseau social
je développe mon propre réseau social, et je n'ai pas trouvé sur le web des exemples de mise en œuvre du flux d'actions des utilisateurs... Par exemple, comment filtrer les actions pour chaque utilisateur? Comment stocker les événements d'action? Quel modèle de données et quel modèle d'objet puis-je utiliser pour le flux d'actions et pour les actions elles-mêmes?
6 réponses
résumé : pour environ 1 million d'utilisateurs actifs et 150 millions d'activités stockées, je fais simple:
- utilisez une base de données relationnelle pour le stockage des activités uniques (1 enregistrement par activité / "chose qui s'est produite") rendre les enregistrements aussi compacts que vous le pouvez. Structure, de sorte que vous pouvez rapidement saisir un lot d'activités par ID d'activité ou un ensemble d'ami Id avec des contraintes de temps.
- publier le ID d'activité à Redis chaque fois qu'un enregistrement d'activité est créé, en ajoutant l'ID à une liste de "flux d'activité" pour chaque utilisateur qui est un ami/abonné qui devrait voir l'activité.
requête Redis pour obtenir le flux d'activités pour n'importe quel utilisateur et puis saisir les données connexes à partir de la base de données au besoin. Revenir à la question de la base de données par le temps si l'Utilisateur a besoin de parcourir loin dans le temps (si vous offrez même cela)
j'utilise un vieille table MySQL pour faire face à environ 15 millions d'activités.
il ressemble à quelque chose comme ceci:
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
me dit le type d'activité, source_id
raconte-moi le dossier que l'activité est liée. Donc si le type d'activité signifie "ajouté favori" alors je sais que source_id se réfère à L'ID d'un enregistrement préféré.
les parent_id
/ parent_type
sont utiles pour mon application - ils me disent ce que l'activité est liée. Si un livre a été favorisé, alors parent_id / parent_type me dirait que l'activité se rapporte à un livre (type) avec une clé primaire donnée (id)
je l'index sur la (user_id, time)
et de la requête pour des activités qui sont user_id IN (...friends...) AND time > some-cutoff-point
. Laisser tomber l'id et choisir un autre index groupé pourrait être une bonne idée - je n'ai pas expérimenté avec cela.
assez basique, mais ça marche, c'est simple, et c'est facile de travailler avec as vos besoins changent. En outre, si vous n'utilisez pas MySQL vous pourriez être en mesure de faire mieux index-Sage.
pour un accès plus rapide aux activités les plus récentes, j'ai expérimenté avec Redis . Redis stocke toutes ses données en mémoire, de sorte que vous ne pouvez pas mettre l'ensemble de vos activités, mais vous pouvez stocker suffisamment pour la plupart des hit écrans sur votre site. Les 100 plus récentes pour chaque utilisateur ou quelque chose comme ça. Avec Redis dans le mélange, il pourrait fonctionner comme ceci:
- Créer votre MySQL activité record
- pour chaque ami de l'utilisateur qui a créé l'activité, insérez L'ID sur la liste D'activités dans Redis.
- couper chaque liste aux derniers x articles
Redis est rapide et offre un moyen de pipeline commandes à travers une connexion afin de pousser une activité à 1000 amis ne prend que quelques millisecondes.
pour une explication plus détaillée de ce dont je parle, voir L'exemple de Twitter de Redis: http://redis.io/topics/twitter-clone
mise à jour février 2011 j'ai 50 millions d'activités actives en ce moment et je n'ai rien changé. Une bonne chose à propos de faire quelque chose de similaire à ceci est qu'il utilise compact, petites rangées. Je prévois de faire quelques changements qui nécessiterait beaucoup plus de activités et plus de questions sur ces activités et je vais certainement utiliser Redis pour garder les choses rapides. J'utilise Redis dans d'autres domaines et cela fonctionne vraiment bien pour certains types de problèmes.
mise à jour juillet 2014 nous sommes jusqu'à environ 700K utilisateurs actifs mensuels. Au cours des deux dernières années, J'ai utilisé Redis (tel que décrit dans la liste à puces) pour stocker les 1000 derniers codes D'activité pour chaque utilisateur. Il ya généralement environ 100 millions d'activités les enregistrements dans le système et ils sont toujours stockés dans MySQL et sont toujours la même mise en page. Ces enregistrements nous permettent de nous en sortir avec moins de mémoire Redis, ils servent d'enregistrement des données d'activité, et nous les utilisons si les utilisateurs ont besoin de page plus loin dans le temps pour trouver quelque chose.
ce n'était pas une solution intelligente ou particulièrement intéressante, mais elle m'a bien servi.
c'est mon implémentation d'un flux d'activités, en utilisant mysql. Il y a trois classes: activité, Activitéfeed, abonné.
activité représente une entrée d'activité, et son tableau ressemble à ceci:
id
subject_id
object_id
type
verb
data
time
Subject_id
est l'id de l'objet l'exécution de l'action, object_id
l'id de l'objet qui reçoit l'action. type
et verb
décrit l'action elle-même (par exemple, si un utilisateur ajouter un commentaire à un article ils seraient "commentaire" et" créé " respectivement), les données contiennent des données supplémentaires afin d'éviter les jointures (par exemple, il peut contenir le nom de l'objet et le nom de famille, le titre de l'article et l'url, le corps du commentaire, etc.).
chaque activité appartient à un ou plusieurs besoins D'activité, et ils sont liés par un tableau qui ressemble à ceci:
feed_name
activity_id
Dans mon application j'ai une alimentation pour chaque Utilisateur et un flux pour chaque Élément (habituellement des articles de blog), mais ils peuvent être ce que vous voulez.
Un Abonné est généralement un utilisateur de votre site, mais il peut aussi être n'importe quel objet dans votre modèle d'objet (par exemple un article pourrait être souscrites à la feed_action de son créateur).
chaque abonné appartient à un ou plusieurs besoins D'activité, et, comme ci-dessus, ils sont liés par une table de lien de ce genre:
feed_name
subscriber_id
reason
le champ reason
explique pourquoi l'abonné a souscrit l'alimentation. Par exemple, si un utilisateur signet un billet de blog, la raison est "signet". Cela m'aide plus tard dans le filtrage des actions pour les notifications aux utilisateurs.
pour récupérer l'activité pour un abonné, je fais une simple jointure des trois tables. Le join est rapide parce que je sélectionne peu d'activités grâce à une WHERE
condition qui ressemble maintenant - time > some hours
. J'évite les autres jointures grâce au champ de données dans la table D'activité.
explication supplémentaire du champ reason
. Si, par exemple, je veux filtrer les actions pour les notifications par e-mail à l'utilisateur, et l'Utilisateur a créé un signet sur un billet de blog (et donc il s'abonne au fil du billet avec la raison "signet"), Je ne veux pas que l'utilisateur reçoive des notifications par e-mail concernant les actions sur cet article, tandis que s'il commente le billet (et donc il s'abonne au fil du billet avec la raison "commentaire") je veux qu'il soit informé lorsque d'autres utilisateurs ajoutent des commentaires au même billet. Raison field m'aide dans cette discrimination (Je l'ai implémenté à travers une classe ActivityFilter), ainsi que les préférences de notification de l'utilisateur.
il y a un format courant pour le flux d'activités qui est développé par un groupe de personnes bien connues.
Fondamentalement, chaque activité a un acteur (qui exécute l'activité), un verbe (l'action de l'activité), un objet (sur lequel l'acteur joue sur), et une cible.
par exemple: Max a posté un lien vers le mur D'Adam.
leur La spécification de JSON a atteint la version 1.0 au moment de l'écriture, qui montre le modèle pour l'activité que vous pouvez appliquer.
leur format a déjà été adopté par BBC, Gnip, Google Buzz Gowalla, IBM, MySpace, Opera, Socialcast, Superfeedr, TypePad, Windows Live, YIID, et bien d'autres.
je pense qu'une explication sur la façon dont le système de notifications fonctionne sur les grands sites Web peut être trouvée dans la question de débordement de pile comment les sites de réseaux sociaux calculent-ils les mises à jour des amis? , dans le Jeremy "Mur de l'151920920" 's réponse. Il suggère l'utilisation de Message Qeue et il indique deux logiciels libres qui l'implémentent:
Voir aussi la question Quelle est la meilleure façon de mettre en œuvre un volet d'activités sociales?
Vous avez absolument besoin d'un performant & distributed file d'attente de messages. Mais il ne s'arrête pas là, vous aurez à prendre des décisions sur ce qu'il faut stocker comme données persistantes et ce que comme transitoire et etc.
de toute façon, c'est vraiment une tâche difficile mon ami si vous êtes après un système de haute performance et évolutif. Mais, bien sûr, certains ingénieurs généreux ont partagé leur expérience à ce sujet. LinkedIn a récemment fait son système de file D'attente de messages Kafka open source. Avant cela, Facebook avait déjà fourni Scribe à la communauté open source. Kafka est écrit en Scala et au début il faut du temps pour le faire fonctionner mais j'ai testé avec quelques serveurs virtuels. Il est vraiment rapide.
http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka /
au lieu de lancer votre propre service, vous pouvez vous tourner vers un service tiers utilisé via une API. J'en ai commencé un qui s'appelle Collabinate ( http://www.collabinate.com ) qui dispose d'une base de données graphique et de quelques algorithmes assez sophistiqués pour traiter de grandes quantités de données d'une manière hautement concurrente et très performante. Bien qu'il n'ait pas l'ampleur des fonctionnalités que Facebook ou Twitter font, il est plus que suffisant pour la plupart des cas d'utilisation où vous avez besoin de construire flux d'activités, flux sociaux ou fonctionnalité de microblogging dans une application.