una sistemas que proyecto nube negocio informatica industry examples escalables escalable escalabilidad ejemplo distribuidos computacional aplicación actividades database database-design social-networking

database - sistemas - Entrega de elementos de alimentación de actividad de forma moderadamente escalable



free database models (1)

La aplicación en la que estoy trabajando tiene un feed de actividad donde cada usuario puede ver la actividad de sus amigos (como Facebook). Estoy buscando una forma moderadamente escalable para mostrar el flujo de actividad de un usuario determinado sobre la marcha. Digo "moderadamente" porque estoy buscando hacer esto solo con una base de datos (Postgresql) y tal vez con memcached. Por ejemplo, quiero que esta solución se amplíe a 200k usuarios con 100 amigos.

Actualmente, hay una tabla de actividades maestras que almacena el html representado para la actividad dada (Jim agregó un amigo, George instaló una aplicación, etc.). Esta tabla de actividad maestra conserva el usuario de origen, el html y una marca de tiempo.

Luego, hay una tabla separada ("unirse") que simplemente mantiene un puntero a la persona que debería ver esta actividad en su feed de amigos, y un puntero al objeto en la tabla de actividades principal.

Por lo tanto, si tengo 100 amigos y hago 3 actividades, entonces la tabla de unión crecerá a 300 artículos.

Claramente esta mesa crecerá muy rápidamente. Sin embargo, tiene la buena propiedad de que la actividad de recuperación para mostrar a un usuario requiere una única consulta (relativamente) de bajo costo.

La otra opción es simplemente mantener la tabla de actividad principal y consultarla diciendo algo como:

select * from activity where source_user in (1, 2, 44, 2423, ... my friend list)

Esto tiene la desventaja de que está consultando a usuarios que quizás nunca estén activos y, a medida que su lista de amigos crezca, esta consulta puede ser cada vez más lenta.

Veo los pros y los contras de ambos lados, pero me pregunto si algunas personas SO podrían ayudarme a sopesar las opciones y sugerir una u otra forma. También estoy abierto a otras soluciones, aunque me gustaría que sea sencillo y no instalar algo como CouchDB, etc.

¡Muchas gracias!


Me estoy inclinando hacia solo tener la mesa de actividades maestra. Si sigues con eso, esto es lo que consideraría implementar:

  1. Puede crear varias tablas de actividades y hacer UNION ALL al recuperar los datos de la base de datos. Por ejemplo, transfiérelos mensualmente - activity_2010_02, etc. Simplemente siguiendo su ejemplo - 200K usuarios x 100 amigos x 3 actividades = 60 millones de filas. No es una preocupación en cuanto al rendimiento para PostgreSQL, pero puede considerar esto solo por conveniencia ahora y eventualmente por una futura expansión sin esfuerzo.

  2. Esto tiene la desventaja de que está consultando a usuarios que quizás nunca estén activos y, a medida que su lista de amigos crezca, esta consulta puede ser cada vez más lenta.

¿Vas a mostrar todo el feed de actividades, volviendo al principio de los tiempos? No ha proporcionado muchos detalles en la pregunta original, pero me atrevería a suponer que estaría mostrando los últimos artículos del 20/10/100 ordenados por marca de tiempo. Un par de índices y la cláusula LIMIT deberían ser suficientes para proporcionar una respuesta instantánea (como acabo de probar en una tabla con aproximadamente 20 millones de filas). Puede ser más lento en un servidor ocupado, pero eso es algo que debería resolverse con el hardware y las soluciones de almacenamiento en caché. Postgres no va a ser el cuello de botella allí.

Incluso si proporciona fuentes de actividad que se remontan a los albores del tiempo, ¡ pagine la salida! La cláusula LIMIT te salvará allí. Si la consulta básica con un LÍMITE no es suficiente, o si sus usuarios tienen una larga cola de amigos que ya no están activos, podría considerar limitar la búsqueda al último día / semana / mes y luego proporcionar la lista de ID de amigos:

select * from activity where ts <= 123456789 and source_user in (1, 2, 44, 2423, ... my friend list)

Si tiene una tabla que abarca meses o años atrás, la búsqueda de los ID de amigos solo se realizará dentro de las filas seleccionadas por la primera cláusula WHERE.

Eso es solo si elijo entre las dos soluciones que está considerando ahora. También me gustaría ver cosas como:

  1. Reconsiderando su desnormalización de la tabla. ¿Almacenar la salida HTML generada previamente es realmente la mejor manera? ¿Estará mejor en términos de rendimiento al tener una tabla de búsqueda de actividades en lugar de generar resultados con plantilla sobre la marcha? El HTML generado previamente puede parecer mejor al principio, pero considerar cosas como el almacenamiento en disco, las API, los futuros cambios en el diseño y el almacenamiento de HTML puede no ser tan atractivo después de todo. La tabla de búsqueda podría contener sus posibles actividades: agregar un amigo, cambiar el estado, etc., y el registro de actividades hará referencia a eso y a la identificación del amigo si otro usuario participa en la actividad.

  2. Realización de código HTML previo, pero sin almacenarlo en la base de datos. Guarda las cosas en el disco como páginas pre-generadas. Sin embargo, esta no es una bala de plata y depende en gran medida de la proporción de escritura para leer en su sitio. Es decir, un hilo de discusión típico en un foro público podría tener una docena de mensajes, pero podría verse cientos de veces, un buen candidato para el almacenamiento en caché. Si su aplicación está más sintonizada con las actualizaciones de estado inmediatas y tendría que volver a generar la página HTML y guardarla nuevamente en el disco después de cada par de vistas, entonces este enfoque tiene poco valor.

Espero que esto ayude.