design-patterns - una - libro adiccion a las redes sociales pdf
Cómo implementar la secuencia de actividad en una red social (6)
Estoy desarrollando mi propia red social, y no he encontrado en la web ejemplos de implementación del flujo de acciones de los usuarios ... Por ejemplo, ¿cómo filtrar acciones para cada usuario? ¿Cómo almacenar los eventos de acción? ¿Qué modelo de datos y modelo de objetos puedo usar para el flujo de acciones y para las acciones en sí?
Creo que una explicación sobre cómo funciona el sistema de notificaciones en sitios web grandes se puede encontrar en la pregunta sobre el desbordamiento de la pila, ¿ cómo los sitios web de redes sociales calculan las actualizaciones de amigos? , en la respuesta de Jeremy Wall . Sugiere el uso de Message Qeue e indica dos softwares de código abierto que lo implementan:
Consulte también la pregunta ¿Cuál es la mejor manera de implementar un flujo de actividad social?
En lugar de enrollar el suyo, podría consultar un servicio de terceros utilizado a través de una API. Empecé uno llamado Collabinate ( http://www.collabinate.com ) que tiene un backend de base de datos de gráficos y algunos algoritmos bastante sofisticados para manejar grandes cantidades de datos de una manera altamente concurrente y de alto rendimiento. Si bien no tiene la amplitud de funcionalidad que dicen Facebook o Twitter, es más que suficiente para la mayoría de los casos de uso en los que necesita generar flujos de actividad, feeds sociales o funcionalidad de microblogging en una aplicación.
Esta es mi implementación de una secuencia de actividad, usando mysql. Hay tres clases: Activity, ActivityFeed, Subscriber.
La actividad representa una entrada de actividad, y su tabla se ve así:
id
subject_id
object_id
type
verb
data
time
Subject_id
es el id del objeto que realiza la acción, object_id
el id del objeto que recibe la acción. type
y verb
describe la acción en sí misma (por ejemplo, si un usuario agrega un comentario a un artículo, sería "comentario" y "creado", respectivamente), los datos contienen datos adicionales para evitar uniones (por ejemplo, puede contener el nombre y apellido del sujeto, título del artículo y url, cuerpo del comentario, etc.).
Cada actividad pertenece a uno o más campos de actividad, y están relacionados por una tabla que se ve así:
feed_name
activity_id
En mi aplicación tengo un feed para cada usuario y un feed para cada artículo (generalmente artículos de blog), pero pueden ser lo que quieras.
Un suscriptor generalmente es un usuario de su sitio, pero también puede ser cualquier objeto en su modelo de objeto (por ejemplo, un artículo podría suscribirse al feed_action de su creador).
Cada suscriptor pertenece a uno o más ActivityFeeds, y, como en el caso anterior, están relacionados por una tabla de enlaces de este tipo:
feed_name
subscriber_id
reason
El campo de reason
aquí explica por qué el suscriptor ha suscrito el feed. Por ejemplo, si un usuario marca una publicación de blog, el motivo es ''marcador''. Esto me ayuda más adelante en las acciones de filtrado para las notificaciones a los usuarios.
Para recuperar la actividad de un suscriptor, hago una simple combinación de las tres tablas. La unión es rápida porque selecciono algunas actividades gracias a una condición WHERE
que se ve como ahora - time > some hours
. Evito otras combinaciones gracias al campo de datos en la tabla de actividades.
Más explicación sobre el campo de la reason
. Si, por ejemplo, quiero filtrar acciones para notificaciones por correo electrónico al usuario, y el usuario marcó una publicación en el blog (y por lo tanto se suscribe a la publicación con el motivo ''marcador''), no deseo que el usuario reciba notificaciones por correo electrónico sobre acciones en ese artículo, mientras que si él comenta la publicación (y por lo tanto se suscribe a la fuente de publicación con el motivo ''comentario'') quiero que se le notifique cuando otros usuarios agreguen comentarios a la misma publicación. El campo de razón me ayuda en esta discriminación (lo implementé a través de una clase ActivityFilter), junto con las preferencias de notificaciones del usuario.
Hay un formato actual para el flujo de actividad que está siendo desarrollado por un grupo de personas conocidas.
Básicamente, cada actividad tiene un actor (que realiza la actividad), un verbo (la acción de la actividad), un objeto (en el que actúa el actor) y un objetivo.
Por ejemplo: Max ha publicado un enlace a la pared de Adam.
La especificación de JSON alcanzó la versión 1.0 en el momento de la redacción, que muestra el patrón de la actividad que puede aplicar.
Su formato ya ha sido adoptado por BBC, Gnip, Google Buzz Gowalla, IBM, MySpace, Opera, Socialcast, Superfeedr, TypePad, Windows Live, YIID y muchos otros.
Necesitas absolutamente una cola de mensajes distribuidos y de rendimiento. Pero no termina ahí, tendrá que tomar decisiones sobre qué almacenar como datos persistentes y qué tipo de transitorios, etc.
De todos modos, es una tarea realmente difícil para mi amigo si buscas un sistema escalable y de alto rendimiento. Pero, por supuesto, algunos ingenieros generosos han compartido su experiencia al respecto. LinkedIn recientemente hizo su sistema de cola de mensajes de código abierto de Kafka. Antes de eso, Facebook ya había proporcionado Scribe a la comunidad de código abierto. Kafka está escrito en Scala y al principio se necesita algo de tiempo para hacerlo funcionar, pero probé con un par de servidores virtuales. Es realmente rápido
http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/
Resumen : para aproximadamente 1 millón de usuarios activos y 150 millones de actividades almacenadas, lo mantengo simple:
- Use una base de datos relacional para el almacenamiento de actividades únicas (1 registro por actividad / "cosa que sucedió") Haga los registros lo más compactos posible. Estructura para poder tomar rápidamente un lote de actividades por ID de actividad o usando un conjunto de ID de amigo con restricciones de tiempo.
- Publique los ID de actividad en Redis cada vez que se cree un registro de actividad, agregando el ID a una lista de "flujo de actividad" para cada usuario que sea un amigo / suscriptor que debería ver la actividad.
Consulta Redis para obtener la secuencia de actividad para cualquier usuario y luego toma los datos relacionados de la base de datos según sea necesario. Vuelva a consultar el db por tiempo si el usuario necesita navegar muy atrás en el tiempo (si incluso ofrece esto)
Utilizo una tabla simple de MySQL para tratar con alrededor de 15 millones de actividades.
Se ve algo como esto:
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 dice el tipo de actividad, source_id
me dice el registro con el que está relacionada la actividad. Entonces, si el tipo de actividad significa "favorito agregado", entonces sé que source_id se refiere a la identificación de un registro favorito.
parent_type
/ parent_type
son útiles para mi aplicación, me dicen a qué se relaciona la actividad. Si un libro fue favorito, entonces parent_id / parent_type me diría que la actividad se relaciona con un libro (tipo) con una clave primaria dada (id)
Indico on (user_id, time)
y consulto las actividades que son user_id IN (...friends...) AND time > some-cutoff-point
. Dejar el ID y elegir un índice agrupado diferente podría ser una buena idea. No he experimentado con eso.
Bastante básico, pero funciona, es simple, y es fácil trabajar con él a medida que cambian sus necesidades. Además, si no está utilizando MySQL, es posible que pueda hacer mejor index-wise.
Para un acceso más rápido a las actividades más recientes, he estado experimentando con Redis . Redis almacena todos sus datos en la memoria, por lo que no puede poner todas sus actividades allí, pero puede almacenar lo suficiente para la mayoría de las pantallas de su sitio. Los 100 más recientes para cada usuario o algo así. Con Redis en la mezcla, podría funcionar así:
- Crea tu registro de actividad MySQL
- Para cada amigo del usuario que creó la actividad, inserte el ID en su lista de actividades en Redis.
- Recortar cada lista a los últimos X elementos
Redis es rápido y ofrece una forma de canalizar comandos a través de una conexión, por lo que llevar una actividad a 1000 amigos lleva milisegundos.
Para una explicación más detallada de lo que estoy hablando, vea el ejemplo de Twitter de Redis: http://redis.io/topics/twitter-clone
Actualización de febrero de 2011 Tengo 50 millones de actividades activas en este momento y no he cambiado nada. Una cosa buena de hacer algo similar a esto es que usa filas compactas y pequeñas. Planeo hacer algunos cambios que involucrarían muchas más actividades y más consultas de esas actividades y definitivamente usaré Redis para mantener las cosas rápidas. Estoy usando Redis en otras áreas y realmente funciona bien para ciertos tipos de problemas.
Actualización de julio de 2014 Tenemos aproximadamente 700,000 usuarios activos mensuales. Durante los últimos años, he estado usando Redis (como se describe en la lista con viñetas) para almacenar los últimos 1000 ID de actividad para cada usuario. Normalmente hay alrededor de 100 millones de registros de actividad en el sistema y todavía se almacenan en MySQL y siguen siendo del mismo diseño. Estos registros nos permiten salirse con menos memoria de Redis, sirven como registro de datos de actividad, y los usamos si los usuarios necesitan una página más atrás en el tiempo para encontrar algo.
Esta no fue una solución inteligente o especialmente interesante, pero me ha sido útil.