Wow, esta es una pregunta simple, que tiene una gran variedad de posibles respuestas. La parte más explícita de su pregunta es si es más escalable interactuar con su base de datos directamente o mediante un servicio web. Esa respuesta es simple: consulta la base de datos directamente. Pasar por el servicio web agrega una gran cantidad de latencia que es completamente innecesaria para el código que opera detrás de un firewall (en general). Un servicio web, por ejemplo, requiere algún componente para recibir una solicitud, deserializarla, consultar la base de datos, serializar una respuesta y devolverla. Entonces, si su código está funcionando detrás de un firewall, ahórrese el problema y simplemente consulte la base de datos directamente.
Sin embargo, hacer que un sitio web sea escalable va mucho más allá de la pregunta que planteó inicialmente. Así que perdóname si salgo por una tangente aquí, pero pensé que podría ser útil teniendo en cuenta que mencionaste Facebook en particular.
Le recomendaría que lea sobre el trabajo y las herramientas creadas por Brad Fitzpatrick (fundador de LiveJournal y ahora en Google). Cuando trabajé con él en Six Apart, estas son algunas de las cosas que aprendí de él y sobre la arquitectura de LiveJournal que lo hizo tan escalable.
Utilice tablas de bases de datos estrechas en lugar de anchas . Lo fascinante de esto fue aprender lo que motivó esta arquitectura, que era crear un sistema que fuera fácil y rápido.actualizado Si usa tablas anchas, o tablas para las cuales cada campo o propiedad es una columna en la tabla, cuando llega el momento de actualizar el esquema de la base de datos, por ejemplo, agregando una nueva columna, entonces el sistema necesitará bloquear la tabla mientras el esquema Se implementa el cambio. Cuando se opera a escala, esto significaría que un simple cambio en el esquema de la base de datos podría provocar una gran interrupción de la base de datos. Lo que obviamente apesta. Por otro lado, una tabla estrecha simplemente almacena cada propiedad individual asociada con un objeto como una sola fila en la base de datos. Por lo tanto, cuando desee agregar una nueva columna a la base de datos, todo lo que necesita hacer es INSERTAR los registros en una tabla, que es una operación sin bloqueo. Ok, eso es un poco de historia, veamos cómo este modelo se traduce realmente en un sistema de trabajo como LiveJournal.
Supongamos que desea cargar las últimas 10 entradas de diario en el blog de una persona, y supongamos que cada entrada de diario tiene diez propiedades. En un diseño clásico de tabla ancha, cada propiedad se correlacionaría con una columna en una tabla. Un usuario luego consultaría la tabla una vez para obtener todos los datos que necesita. La consulta devolvería 10 filas y cada fila tendría todos los datos que necesitan (por ejemplo, SELECCIONAR * DESDE las entradas ORDENAR POR fecha LÍMITE 10). Sin embargo, en un diseño de tabla estrecho las cosas son un poco diferentes. En este ejemplo, en realidad hay dos tablas: la primera tabla (tabla A) almacena criterios simples que uno desearía buscar, por ejemplo, la identificación de la entrada, la identificación del autor, la fecha de la entrada, etc. Una segunda tabla (tabla B) luego almacena todas las propiedades asociadas con una entrada. Esta segunda tabla tiene tres columnas: entry_id, key y value. Por cada fila en la tabla A, habría 10 filas en la tabla B (una fila para cada propiedad). Por lo tanto, para obtener y mostrar las últimas diez entradas, necesitará 11 consultas. La primera consulta le proporciona la lista de ID de entrada, y luego las siguientes diez consultas obtendrían las propiedades asociadas con cada una de las entradas devueltas en la primera consulta.
"¡Santo Moly!" dices, "¿cómo puede eso ser más escalable?" Es totalmente contrario a la intuición, ¿verdad? En el primer escenario, solo tuvimos una consulta a la base de datos, pero en la segunda solución "más escalable" tenemos 11 consultas a la base de datos. Eso no tiene sentido. La respuesta a esa pregunta se basa completamente en la siguiente viñeta.
Use memcache generosamente. En caso de que no lo supiera, memcache es un sistema de almacenamiento en caché distribuido, sin estado, de baja latencia y basado en red. Lo utilizan Facebook, Google, Yahoo y casi todos los sitios web populares y escalables del planeta. Fue inventado por Brad Fitzpatrick parcialmente para ayudar a compensar la sobrecarga de la base de datos inherente a un diseño de base de datos de tabla estrecha. Echemos un vistazo al mismo ejemplo que se discutió en el punto 1 anterior, pero esta vez, presentemos memcache.
Comencemos cuando un usuario visita por primera vez una página y no hay nada en la memoria caché. Comienza por consultar la tabla A que devuelve los ID de las 10 entradas que desea mostrar en la página. Para cada una de esas entradas, consulta la base de datos para recuperar las propiedades asociadas con esa entrada, y luego usar esas propiedades constituye un objeto con el que su código puede interactuar (por ejemplo, un objeto). Luego oculta ese objeto (o una forma serializada de ese objeto) en memcache.
La segunda vez que alguien carga la misma página, comienza de la misma manera: al consultar en la tabla A la lista de ID de entradas que mostrará. Para cada entrada, primero vaya a memcache y diga: "¿tiene la entrada #X en el caché?" En caso afirmativo, memcache le devuelve el objeto de entrada. De lo contrario, debe volver a consultar la base de datos para obtener sus propiedades, constituir el objeto y guardarlo en Memcache. La mayoría de las veces, la segunda vez que alguien visita la misma página solo hay una consulta de base de datos, todos los demás datos se extraen directamente de memcache.
En la práctica, lo que terminó sucediendo para la mayoría de LiveJournal es que la mayoría de los datos del sistema, especialmente los datos menos volátiles, se almacenaron en caché en Memcache y las consultas adicionales a la base de datos necesarias para admitir el esquema de tabla estrecha se compensaron por completo.
Este diseño hizo que resolver el problema asociado con el ensamblaje de una lista de publicaciones asociadas con todos tus amigos en una transmisión, o "muro", fuera mucho , mucho más fácil.
Luego, considere particionar su base de datos. El modelo discutido anteriormente presenta otro problema, y es que sus tablas estrechas tenderán a ser muy grandes / largas. Y mientras más filas tengan esas tablas, más difíciles se volverán otras tareas administrativas. Para compensar esto, podría tener sentido administrar el tamaño de sus tablas mediante la partición de las tablas de alguna manera, de modo que los grupos de usuarios sean atendidos por una base de datos, y otro grupo de usuarios sea atendido por una base de datos separada. Esto distribuye la carga en la base de datos y mantiene las consultas eficientes.
Finalmente, necesitas índices increíbles. La velocidad de sus consultas dependerá en gran medida de lo bien indexadas que estén las tablas de su base de datos. No pasaré demasiado tiempo discutiendo qué es un índice, excepto para decir que es muy parecido a un sistema de catálogo de tarjetas gigante para hacer que la búsqueda de agujas en un pajar sea más eficiente. Si usa mysql, le recomiendo activar el registro lento de consultas para monitorear las consultas que demoran mucho tiempo en completarse. Cuando aparezca una consulta en su radar (por ejemplo, porque es lenta), descubra qué índice necesita agregar a la tabla para acelerarla.
"Gracias por todos estos excelentes antecedentes, pero santo cielo, es mucho código que tendré que escribir".
No necesariamente. Se han escrito muchas bibliotecas que facilitan la interacción con memcache. Aún otras bibliotecas han codificado todo el proceso descrito anteriormente; Data :: ObjectDriver en Perl es solo una biblioteca de este tipo. En cuanto a otros idiomas, deberá hacer su propia investigación.
Espero que hayas encontrado útil esta respuesta. Lo que he encontrado la mayoría de las veces es que la escalabilidad de un sistema a menudo se reduce cada vez menos al código, y cada vez más a una estrategia de almacenamiento de datos y un diseño técnico.