Je développe mon propre réseau social, et je n'ai pas trouvé sur le web d'exemples d'implémentation 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?
design-patterns
architecture
stream
social-networking
Nicolò Martini
la source
la source
Réponses:
Résumé : Pour environ 1 million d'utilisateurs actifs et 150 millions d'activités stockées, je reste simple:
Interrogez Redis pour obtenir le flux d'activité de n'importe quel utilisateur, puis récupérez les données associées de la base de données si nécessaire. Revenez à l'interrogation de la base de données par heure si l'utilisateur a besoin de naviguer très loin dans le temps (si vous offrez même cela)
J'utilise une vieille table MySQL pour traiter environ 15 millions d'activités.
Cela ressemble à quelque chose comme ceci:
activity_type
me dit le type d'activité,source_id
me dit le record auquel l'activité est liée. Donc, si le type d'activité signifie "favori ajouté", je sais que le source_id fait référence à l'ID d'un enregistrement favori.Le
parent_id
/parent_type
sont utiles pour mon application - ils me disent à quoi l'activité est liée. Si un livre a été ajouté aux favoris, alors parent_id / parent_type me dirait que l'activité se rapporte à un livre (type) avec une clé primaire (id) donnéeJ'indexe
(user_id, time)
et interroge les activités qui le sontuser_id IN (...friends...) AND time > some-cutoff-point
. Abandonner l'identifiant et choisir un autre index clusterisé pourrait être une bonne idée - je n'ai pas expérimenté cela.Des trucs assez basiques, mais cela fonctionne, c'est simple et il est facile de travailler avec lorsque vos besoins changent. De plus, si vous n'utilisez pas MySQL, vous pourrez peut-être faire mieux en termes d'index.
Pour accéder plus rapidement aux activités les plus récentes, j'ai expérimenté Redis . Redis stocke toutes ses données en mémoire, vous ne pouvez donc pas y placer toutes vos activités, mais vous pouvez en stocker suffisamment pour la plupart des écrans les plus fréquemment consultés sur votre site. Les 100 plus récents pour chaque utilisateur ou quelque chose comme ça. Avec Redis dans le mix, cela pourrait fonctionner comme ceci:
Redis est rapide et offre un moyen de canaliser les commandes sur une seule connexion - donc, pousser une activité à 1000 amis prend des millisecondes.
Pour une explication plus détaillée de ce dont je parle, voir l'exemple Twitter de Redis: http://redis.io/topics/twitter-clone
Mise à jour Février 2011 J'ai actuellement 50 millions d'activités actives et je n'ai rien changé. Une bonne chose à propos de faire quelque chose de similaire est qu'il utilise de petites lignes compactes. Je prévois d'apporter des changements qui impliqueraient beaucoup plus d'activités et plus de requêtes sur ces activités et j'utiliserai certainement Redis pour accélérer les choses. 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 700 000 utilisateurs actifs par mois. Depuis quelques années, j'utilise Redis (comme décrit dans la liste à puces) pour stocker les 1000 derniers identifiants d'activité de chaque utilisateur. Il y a généralement environ 100 millions d'enregistrements d'activité dans le système et ils sont toujours stockés dans MySQL et ont toujours la même disposition. 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 reculer dans le temps pour trouver quelque chose.
Ce n'était pas une solution intelligente ou particulièrement intéressante, mais cela m'a bien servi.
la source
JOIN
sur les différentesactivity_type
tables? Ces jointures sont-elles coûteuses en termes de performances?activity_type
pour obtenir les autres données dont vous avez besoin.Ceci est mon implémentation d'un flux d'activité, en utilisant mysql. Il existe trois classes: Activity, ActivityFeed, Subscriber.
L'activité représente une entrée d'activité et sa table ressemble à ceci:
Subject_id
est l'identifiant de l'objet exécutant l'action,object_id
l'id de l'objet qui reçoit l'action.type
etverb
décrit l'action elle-même (par exemple, si un utilisateur ajoute un commentaire à un article, il serait respectivement "commentaire" et "créé"), les données contiennent des données supplémentaires afin d'éviter les jointures (par exemple, elles peuvent contenir le nom du sujet et nom, le titre et l'url de l'article, le corps du commentaire, etc.).Chaque activité appartient à un ou plusieurs ActivityFeeds, et ils sont liés par une table qui ressemble à ceci:
Dans mon application, j'ai un flux pour chaque utilisateur et un flux pour chaque élément (généralement 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 s'agir de n'importe quel objet de votre modèle objet (par exemple, un article pourrait être abonné au feed_action de son créateur).
Chaque Abonné appartient à un ou plusieurs ActivityFeeds, et, comme ci-dessus, ils sont liés par une table de liens de ce type:
Le
reason
champ ici explique pourquoi l'abonné s'est abonné au flux. Par exemple, si un utilisateur ajoute un signet à un article de blog, la raison est «signet». Cela m'aide plus tard à filtrer les actions pour les notifications aux utilisateurs.Pour récupérer l'activité d'un abonné, je fais une simple jointure des trois tables. La jointure est rapide car je sélectionne peu d'activités grâce à une
WHERE
condition qui ressemble maintenant -time > some hours
. J'évite d'autres jointures grâce au champ de données dans la table d'activité.Plus d'explications sur le
reason
terrain. Si, par exemple, je souhaite filtrer les actions pour les notifications par e-mail à l'utilisateur et que l'utilisateur a mis un article de blog en signet (et qu'il s'abonne donc au fil de publication avec la raison `` signet ''), je ne veux pas que l'utilisateur reçoive notifications par e-mail sur les actions sur cet élément, tandis que s'il commente le message (et qu'il s'abonne au fil de publication avec la raison `` commentaire ''), je veux qu'il soit averti lorsque d'autres utilisateurs ajoutent des commentaires sur le même message. Le champ raison m'aide dans cette discrimination (je l'ai implémenté via une classe ActivityFilter), ainsi que les préférences de notification de l'utilisateur.la source
Il existe un format actuel pour le flux d'activités qui est développé par un groupe de personnes bien connues.
http://activitystrea.ms/ .
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) et une cible.
Par exemple: Max a publié un lien vers le mur d'Adam.
Leur spécification JSON a atteint la version 1.0 au moment de la rédaction, ce qui montre le modèle de 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.
la source
Je pense qu'une explication sur le fonctionnement du système de notifications 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 la réponse de Jeremy Wall . Il suggère l'utilisation de Message Qeue et il indique deux logiciels open source qui l'implémentent:
Voir aussi la question Quelle est la meilleure manière de mettre en œuvre un flux d'activité sociale?
la source
Vous avez absolument besoin d'une file d'attente de messages performante et distribuée. Mais cela ne s'arrête pas là, vous devrez prendre des décisions sur ce qu'il faut stocker en tant que données persistantes et ce qui est transitoire, etc.
Quoi qu'il en soit, c'est vraiment une tâche difficile mon ami si vous recherchez un système performant et évolutif. Mais, bien sûr, certains ingénieurs généreux ont partagé leur expérience à ce sujet. LinkedIn a récemment rendu 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 un certain temps pour le faire fonctionner, mais j'ai testé avec quelques serveurs virtuels. C'est vraiment rapide.
http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/
http://incubator.apache.org/kafka/index.html
la source
Au lieu de lancer le vôtre, vous pouvez vous tourner vers un service tiers utilisé via une API. J'en ai lancé un appelé Collabinate ( http://www.collabinate.com ) qui a un backend de base de données de graphes et des algorithmes assez sophistiqués pour gérer de grandes quantités de données de manière hautement simultanée et hautement performante. Bien qu'il n'ait pas l'étendue des fonctionnalités que disent Facebook ou Twitter, cela suffit largement pour la plupart des cas d'utilisation où vous devez créer des flux d'activité, des flux sociaux ou des fonctionnalités de microblogage dans une application.
la source