Estoy interesado en escuchar sus opiniones sobre cuál es la mejor manera de implementar un flujo de actividad social (Facebook es el ejemplo más famoso). Los problemas / desafíos involucrados son:
- Diferentes tipos de actividades (publicar, comentar ...)
- Diferentes tipos de objetos (post, comentario, foto ...)
- 1-n usuarios involucrados en diferentes roles ("Usuario x respondió al comentario del Usuario y en la publicación Z del Usuario")
- Diferentes vistas del mismo elemento de actividad ("usted comentó .." vs. "su amigo x comentó" vs. "usuario x comentó .." => 3 representaciones de una actividad de "comentario")
.. y algo más, especialmente si lo lleva a un alto nivel de sofisticación, como lo hace Facebook, por ejemplo, combinando varios elementos de actividad en uno ("los usuarios x, y y z comentaron esa foto"
Cualquier comentario o sugerencia sobre patrones, documentos, etc. sobre los enfoques más flexibles, eficientes y potentes para implementar dicho sistema, modelo de datos, etc. sería apreciado.
Aunque la mayoría de los problemas son independientes de la plataforma, es probable que termine implementando dicho sistema en Ruby on Rails
fuente
Esta es una muy buena presentación que describe cómo Etsy.com diseñó sus flujos de actividad. Es el mejor ejemplo que he encontrado sobre el tema, aunque no se trata de rieles específicos.
http://www.slideshare.net/danmckinley/etsy-activity-feeds-architecture
fuente
Hemos abierto nuestro enfoque: https://github.com/tschellenbach/Stream-Framework Actualmente es la biblioteca de código abierto más grande destinada a resolver este problema.
El mismo equipo que creó Stream Framework también ofrece una API alojada, que maneja la complejidad por usted. Eche un vistazo a getstream.io Hay clientes disponibles para Node, Python, Rails y PHP.
Además, eche un vistazo a esta publicación de alta escalabilidad donde explicamos algunas de las decisiones de diseño involucradas: http://highscalability.com/blog/2013/10/28/design-decisions-for-scaling-your-high-traffic- feeds.html
Este tutorial lo ayudará a configurar un sistema como el feed de Pinterest con Redis. Comenzar es bastante fácil.
Para obtener más información sobre el diseño de feed, recomiendo leer algunos de los artículos en los que basamos Feedly:
Aunque Stream Framework está basado en Python, no sería demasiado difícil de usar desde una aplicación Ruby. Simplemente puede ejecutarlo como un servicio y pegar una pequeña API http delante de él. Estamos considerando agregar una API para acceder a Feedly desde otros idiomas. Sin embargo, por el momento tendrás que interpretar el tuyo.
fuente
Los mayores problemas con las transmisiones de eventos son la visibilidad y el rendimiento; debe restringir los eventos que se muestran para que sean solo los interesantes para ese usuario en particular, y debe mantener la cantidad de tiempo necesario para clasificar e identificar esos eventos manejables. He construido una red social pequeña; Descubrí que a pequeñas escalas, mantener una tabla de "eventos" en una base de datos funciona, pero que puede ser un problema de rendimiento bajo una carga moderada.
Con un flujo mayor de mensajes y usuarios, probablemente sea mejor ir con un sistema de mensajería, donde los eventos se envían como mensajes a perfiles individuales. Esto significa que no puede suscribirse fácilmente a las secuencias de eventos de las personas y ver eventos anteriores con mucha facilidad, pero simplemente está representando un pequeño grupo de mensajes cuando necesita representar la secuencia para un usuario en particular.
Creo que este fue el defecto de diseño original de Twitter. Recuerdo haber leído que estaban golpeando la base de datos para ingresar y filtrar sus eventos. Esto tenía todo que ver con la arquitectura y nada que ver con Rails, que (desafortunadamente) dio a luz al meme "rubí no escala". Hace poco vi una presentación en la que el desarrollador utilizó el servicio Simple Queue de Amazon como su backend de mensajería para una aplicación similar a Twitter que tendría capacidades de escalamiento mucho más altas; puede valer la pena mirar a SQS como parte de su sistema, si sus cargas son lo suficientemente altas .
fuente
Si está dispuesto a usar un software separado, le sugiero el servidor Graphity que resuelve exactamente el problema de los flujos de actividad (construyendo sobre la base de datos del gráfico neo4j).
Los algoritmos se han implementado como un servidor REST independiente para que pueda alojar su propio servidor para entregar flujos de actividad: http://www.rene-pickhardt.de/graphity-server-for-social-activity-streams-released-gplv3 / /
En el documento y en el punto de referencia, mostré que la recuperación de flujos de noticias depende solo linealmente de la cantidad de elementos que desea recuperar sin ninguna redundancia que obtendría al desnormalizar los datos:
http://www.rene-pickhardt.de/graphity-an-efficient-graph-model-for-retrieving-the-top-k-news-feeds-for-users-in-social-networks/
En el enlace de arriba encontrará capturas de pantalla y un punto de referencia de este enfoque (que muestra que Graphity puede recuperar más de 10k transmisiones por segundo).
fuente
Empecé a implementar un sistema como este ayer, aquí es donde tengo que ...
Creé una clase StreamEvent con las propiedades Id , ActorId , TypeId , Date , ObjectId y una tabla hash de pares de clave / valor Detalles adicionales . Esto se representa en la base de datos por un StreamEvent mesa ( Id , actorId , TypeId , Fecha , OBJECTID ) y un StreamEventDetails mesa ( StreamEventId , DetailKey , DetailValue ).
El ActorId , TypeId y ObjectId permiten capturar un evento sujeto-verbo-objeto (y luego consultarlo). Cada acción puede dar lugar a la creación de varias instancias de StreamEvent.
Luego he creado una subclase para StreamEvent para cada tipo de evento, por ejemplo , LoginEvent , PictureCommentEvent . Cada una de estas subclases tiene propiedades más específicas de contexto, como PictureId , ThumbNail , CommenText , etc. (lo que sea necesario para el evento) que en realidad se almacenan como pares clave / valor en la tabla hashtable / StreamEventDetail.
Al retirar estos eventos de la base de datos, uso un método de fábrica (basado en el TypeId ) para crear la clase StreamEvent correcta.
Cada subclase de StreamEvent tiene un método Render ( contexto como StreamContext ) que genera el evento en la pantalla en función de la clase StreamContext aprobada . La clase StreamContext permite establecer opciones en función del contexto de la vista. Si mira Facebook, por ejemplo, su feed de noticias en la página de inicio enumera los nombres completos (y los enlaces a su perfil) de todos los involucrados en cada acción, mientras que al mirar el feed de un amigo solo ve su nombre (pero los nombres completos de otros actores) .
Todavía no he implementado un feed agregado (página de inicio de Facebook), pero imagino que crearé una tabla AggregateFeed que tiene los campos UserId , StreamEventId que se basa en algún tipo de algoritmo 'Hmmm, puede que le resulte interesante'.
Cualquier comentario sería enormemente apreciado.
fuente
Cuando se crea el evento, decida en qué fuentes aparece y agréguelos a events_feeds. Para obtener un feed, seleccione de events_feeds, únase a eventos, ordene por marca de tiempo. El filtrado y la agregación se pueden hacer en los resultados de esa consulta. Con este modelo, puede cambiar las propiedades del evento después de la creación sin trabajo adicional.
fuente
Si decide que va a implementar en Rails, quizás encuentre útil el siguiente complemento:
ActivityStreams: http://github.com/face/activity_streams/tree/master
Por lo menos, podrá ver una implementación, tanto en términos del modelo de datos, como de la API proporcionada para las actividades de empujar y tirar.
fuente
Tuve un enfoque similar al de heyman: una tabla desnormalizada que contiene todos los datos que se mostrarían en un flujo de actividad determinado. Funciona bien para un sitio pequeño con actividad limitada.
Como se mencionó anteriormente, es probable que enfrente problemas de escalabilidad a medida que el sitio crece. Personalmente, no estoy preocupado por los problemas de escala en este momento. Me preocuparé por eso en otro momento.
Obviamente, Facebook ha hecho un gran trabajo de escala, por lo que le recomendaría que lea su blog de ingeniería, ya que tiene un montón de excelente contenido -> http://www.facebook.com/notes.php?id=9445547199
He estado buscando mejores soluciones que la tabla desnormalizada que mencioné anteriormente. Otra forma que he encontrado de lograr esto es condensar todo el contenido que estaría en un flujo de actividad dado en una sola fila. Podría almacenarse en XML, JSON o algún formato serializado que su aplicación pueda leer. El proceso de actualización también sería simple. Luego de la actividad, coloque la nueva actividad en una cola (tal vez usando Amazon SQS u otra cosa) y luego sondee continuamente la cola para el siguiente elemento. Tome ese elemento, analícelo y coloque su contenido en el objeto de fuente apropiado almacenado en la base de datos.
Lo bueno de este método es que solo necesita leer una sola tabla de base de datos cada vez que se solicita ese feed en particular, en lugar de tomar una serie de tablas. Además, le permite mantener una lista finita de actividades, ya que puede mostrar el elemento de actividad más antiguo cada vez que actualice la lista.
¡Espero que esto ayude! :)
fuente
Hay dos railscasts sobre este flujo de actividad:
Esas soluciones no incluyen todos sus requisitos, pero deberían darle algunas ideas.
fuente
Creo que el enfoque de Plurk es interesante: proporcionan toda su línea de tiempo en un formato que se parece mucho a los gráficos de acciones de Google Finance.
Puede valer la pena mirar a Ning para ver cómo funciona una red de redes sociales. Las páginas del desarrollador parecen especialmente útiles.
fuente
Resolví esto hace unos meses, pero creo que mi implementación es demasiado básica.
Creé los siguientes modelos:
Ejemplo
fuente
Después de implementar flujos de actividad para habilitar las funciones de alimentación social, microblogging y colaboración en varias aplicaciones, me di cuenta de que la funcionalidad básica es bastante común y podría convertirse en un servicio externo que puede utilizar a través de una API. Si está integrando el flujo en una aplicación de producción y no tiene necesidades únicas o profundamente complejas, utilizar un servicio comprobado puede ser la mejor opción. Definitivamente recomendaría esto para aplicaciones de producción en lugar de rodar su propia solución simple sobre una base de datos relacional.
Mi empresa Collabinate ( http://www.collabinate.com ) surgió de esta realización, y hemos implementado un motor de flujo de actividad escalable y de alto rendimiento en la parte superior de una base de datos gráfica para lograrlo. De hecho, utilizamos una variante del algoritmo Graphity (adaptado del trabajo inicial de @RenePickhardt, que también proporcionó una respuesta aquí) para construir el motor.
Si desea alojar el motor usted mismo o necesita una funcionalidad especializada, el código central es en realidad de código abierto para fines no comerciales, por lo que puede echarle un vistazo.
fuente