Estoy comenzando a construir un sistema de notificación de estilo Facebook para nuestra página (tipo de juego social) y ahora estoy investigando cuál sería la mejor manera de diseñar dicho sistema. No estoy interesado en cómo enviar notificaciones al usuario ni nada por el estilo (por ahora incluso). Estoy investigando cómo construir el sistema en el servidor (cómo almacenar notificaciones, dónde almacenarlas, cómo buscarlas, etc.).
Entonces ... algunos requisitos que tenemos:
- en las horas pico tenemos alrededor de 1k usuarios concurrentes conectados (y muchos más invitados, pero no importan aquí ya que no tendrán notificaciones) que generarán muchos eventos
- habrá diferentes tipos de notificaciones (el usuario A te ha agregado como amigo, el usuario B ha comentado tu perfil, al usuario C le ha gustado tu imagen, el usuario D te ha ganado en el juego X, ...)
- la mayoría de los eventos generarán 1 notificación para 1 usuario (al usuario X le ha gustado su imagen), pero habrá casos en los que un evento generará muchas notificaciones (por ejemplo, es el cumpleaños del usuario Y)
- las notificaciones deben agruparse juntas; si, por ejemplo, a cuatro usuarios diferentes les gusta alguna imagen, el propietario de esa imagen debería recibir una notificación que indique que a cuatro usuarios les gustó la imagen y no cuatro notificaciones separadas (al igual que FB)
Bien, lo que estaba pensando es que debería crear algún tipo de cola donde almacenaría eventos cuando ocurrieran. Entonces tendría un trabajo de fondo ( ¿ gearman ?) Que miraría esa cola y generaría notificaciones basadas en esos eventos. Este trabajo luego almacenaría notificaciones en la base de datos para cada usuario (por lo que si un evento afecta a 10 usuarios, habría 10 notificaciones separadas). Luego, cuando el usuario abría una página con la lista de notificaciones, leía todas esas notificaciones para él (pensamos limitar esto a las 100 últimas notificaciones) y las agrupaba y finalmente las mostraba.
Cosas que me preocupan con este enfoque:
- complejo como el infierno :)
- es la base de datos el mejor almacenamiento aquí (estamos usando MySQL) o debería usar otra cosa (redis parece ser una buena opción también)
- ¿Qué debo guardar como notificación? ID de usuario, ID de usuario que inició el evento, tipo de evento (para que pueda agruparlos y mostrar el texto apropiado) pero luego no sé cómo almacenar los datos reales de la notificación (por ejemplo, URL y título de la imagen que me gustó). ¿Debo "hornear" esa información cuando genero la notificación, o debo almacenar la identificación del registro (imagen, perfil, ...) afectado y extraer la información de la base de datos cuando muestre la notificación?
- el rendimiento debería estar bien aquí, incluso si tengo que procesar 100 notificaciones sobre la marcha cuando visualizo la página de notificaciones
- posible problema de rendimiento en cada solicitud porque tendría que mostrar el número de notificaciones no leídas al usuario (lo que podría ser un problema en sí mismo ya que agruparía las notificaciones). Sin embargo, esto podría evitarse si generara la vista de notificaciones (donde están agrupadas) en segundo plano y no sobre la marcha
Entonces, ¿qué opinas sobre mi solución propuesta y mis preocupaciones? Comente si cree que debería mencionar algo más que sería relevante aquí.
Oh, estamos usando PHP para nuestra página, pero eso no debería ser un gran factor aquí, creo.
fuente
Respuestas:
Una notificación es sobre algo (objeto = evento, amistad ...) que alguien (actor) le ha cambiado (verbo = agregado, solicitado ...) y lo ha informado al usuario (sujeto). Aquí hay una estructura de datos normalizada (aunque he usado MongoDB). Debe notificar a ciertos usuarios sobre los cambios. Entonces, son notificaciones por usuario ... lo que significa que si hubiera 100 usuarios involucrados, generaría 100 notificaciones.
(Agregue campos de tiempo donde mejor le parezca)
Esto es básicamente para agrupar cambios por objeto, para que pueda decir "Tiene 3 solicitudes de amistad". Y la agrupación por actor es útil, por lo que podría decir "El usuario James Bond hizo cambios en su cama". Esto también brinda la capacidad de traducir y contar las notificaciones a su gusto.
Pero, dado que el objeto es solo una ID, necesitaría obtener toda la información adicional sobre el objeto que desea con llamadas separadas, a menos que el objeto realmente cambie y desee mostrar ese historial (por ejemplo, "el usuario cambió el título del evento a ... ")
Dado que las notificaciones están cerca del tiempo real para los usuarios en el sitio, las vincularía con el cliente nodejs + websockets con php que empuja la actualización a nodejs para todos los oyentes a medida que se agrega el cambio.
fuente
is_notification_read
en lanotification
tabla y marcarlo apropiadamente si esunread
,read
odeleted
.Esta es realmente una pregunta abstracta, así que supongo que tendremos que discutirla en lugar de señalar lo que debe o no debe hacer.
Esto es lo que pienso sobre sus preocupaciones:
Sí, un sistema de notificación es complejo, pero no tan infernal. Puede tener muchos enfoques diferentes para modelar e implementar tales sistemas, y pueden tener desde un nivel medio hasta un alto nivel de complejidad;
Pesonalmente, siempre trato de hacer cosas basadas en bases de datos. ¿Por qué? Porque puedo garantizar tener el control total de todo lo que está sucediendo, pero solo soy yo, puedes tener el control sin un enfoque basado en la base de datos; confía en mí, querrás controlar ese caso;
Permítame ejemplificar un caso real para usted, para que pueda comenzar desde algún lugar. El año pasado modelé e implementé un sistema de notificación en algún tipo de red social (no como Facebook, por supuesto). ¿La forma en que solía almacenar notificaciones allí? Tenía una
notifications
tabla, donde guardaba lagenerator_user_id
(la identificación del usuario que está generando la notificación), latarget_user_id
(tipo de obvio, ¿no?), Lanotification_type_id
(que hacía referencia a una tabla diferente con tipos de notificación) y todo esas cosas necesarias con las que necesitamos llenar nuestras tablas (marcas de tiempo, banderas, etc.). Minotification_types
tabla solía tener una relación con unanotification_templates
tabla, que almacenaba plantillas específicas para cada tipo de notificación. Por ejemplo, tenía unPOST_REPLY
tipo, que tenía una plantilla similar{USER} HAS REPLIED ONE OF YOUR #POSTS
. A partir de ahí, acabo de tratar el{}
como variable y#
como enlace de referencia;Sí, el rendimiento debe y debe estar bien. Cuando piensa en notificaciones, piensa en el servidor empujando de pies a cabeza. Si lo vas a hacer con solicitudes de ajax o lo que sea, tendrás que preocuparte por el rendimiento. Pero creo que es una segunda preocupación;
El modelo que he diseñado no es, por supuesto, el único que puedes seguir, ni tampoco el mejor. Espero que mi respuesta, al menos, te siga en la dirección correcta.
fuente
Esta parece una buena respuesta en lugar de tener 2 colecciones. Puede consultar por nombre de usuario, objeto e isRead para obtener nuevos eventos (como 3 solicitudes de amistad pendientes, 4 preguntas, etc.)
Avíseme si hay algún problema con este esquema.
fuente
Personalmente, no entiendo muy bien el diagrama de la respuesta aceptada, por lo que adjuntaré una base de diagrama de base de datos sobre lo que podría aprender de la respuesta aceptada y otras páginas.
Las mejoras son bien recibidas.
fuente