Pregunta

Estoy trabajando en una aplicación web que se encuentra entre un servicio de correo electrónico y una red social. Siento que tiene el potencial de crecer realmente en el futuro, así que me preocupa la escalabilidad.

En lugar de utilizar una base de datos centralizada MySQL / InnoDB y luego particionarla cuando llegue el momento, he decidido crear una base de datos SQLite separada para cada usuario activo: un usuario activo por 'fragmento'.

De esa manera, hacer una copia de seguridad de la base de datos sería tan fácil como copiar el archivo de base de datos small de cada usuario en una ubicación remota una vez al día.

La ampliación será tan fácil como agregar discos duros adicionales para almacenar los nuevos archivos.

Cuando la aplicación crece más allá de un solo servidor, puedo vincular los servidores en el nivel del sistema de archivos usando GlusterFS y ejecutar la aplicación sin cambios, o armar un simple sistema proxy SQLite que permitirá a cada servidor manipular archivos sqlite en servidores adyacentes.

Los problemas de concurrencia serán mínimos porque cada solicitud HTTP solo tocará uno o dos archivos de base de datos a la vez, de miles, y SQLite solo bloquea las lecturas de todos modos.

Apuesto a que este enfoque permitirá que mi aplicación se escale con gracia y admita muchas características interesantes y únicas . ¿Estoy apostando mal? ¿Me estoy perdiendo algo?

ACTUALIZACIÓN decidí optar por una solución menos extrema, que hasta ahora funciona bien. Estoy usando un número fijo de fragmentos: 256 bases de datos sqlite, para ser precisos. Cada usuario es asignado y vinculado a un fragmento aleatorio por una simple función hash.

La mayoría de las funciones de mi aplicación requieren acceso a solo uno o dos fragmentos por solicitud, pero hay uno en particular que requiere la ejecución de una consulta simple en 10 a 100 fragmentos diferentes de 256, dependiendo del usuario. Las pruebas indican que tomaría aproximadamente 0.02 segundos, o menos, si todos los datos se almacenan en caché en la RAM. ¡Creo que puedo vivir con eso!

ACTUALIZACIÓN 2.0 porté la aplicación a MySQL / InnoDB y pude obtener el mismo rendimiento para las solicitudes regulares, pero para esa solicitud que requiere caminar por fragmentos, innodb es 4-5 veces más rápido . Por esta razón, y por otra razón, estoy descartando esta arquitectura, pero espero que alguien en algún lugar la encuentre ... gracias.

¿Fue útil?

Solución

El lugar donde esto fallará es si tienes que hacer lo que se llama "caminar a trozos". - que es encontrar todos los datos en un grupo de usuarios diferentes. Ese tipo particular de "consulta" tendrá que hacerse mediante programación, preguntando a cada una de las bases de datos SQLite a su vez, y muy probablemente será el aspecto más lento de su sitio. Es un problema común en cualquier sistema donde los datos se han "fragmentado" en bases de datos separadas.

Si todos los datos son independientes para el usuario, entonces esto debería escalar bastante bien: la clave para hacer de este un diseño efectivo es saber cómo es probable que se usen los datos y si los datos de una persona interactuará con datos de otro (en su contexto).

También es posible que tenga que estar atento a los recursos del sistema de archivos (SQLite es excelente, impresionante, rápido, etc.), pero obtiene algunos beneficios de almacenamiento en caché y escritura al usar una "base de datos estándar". (es decir, MySQL, PostgreSQL, etc.) debido a cómo están diseñados. En su diseño propuesto, se perderá algo de eso.

Otros consejos

Me parece una pesadilla de mantenimiento. ¿Qué sucede cuando el esquema cambia en todos esos DB?

Un posible problema es que tener una base de datos para cada usuario utilizará el espacio en disco y la RAM de manera muy ineficiente, y a medida que la base de usuarios crezca, el beneficio de usar un motor de base de datos ligero y rápido se perderá por completo.

Una posible solución a este problema es crear " minishards " que consta de quizás 1024 bases de datos SQLite que albergan hasta 100 usuarios cada una . Esto será más eficiente que el enfoque de DB por usuario, porque los datos se empaquetan de manera más eficiente. Y más ligero que el enfoque del servidor de base de datos Innodb, porque estamos usando Sqlite.

La concurrencia también será bastante buena, pero las consultas serán menos elegantes (shard_id yuckiness). ¿Qué te parece?

http://freshmeat.net/projects/sphivedb

SPHiveDB es un servidor para la base de datos sqlite. Utiliza JSON-RPC sobre HTTP para exponer una interfaz de red para usar la base de datos SQLite. Admite combinar múltiples bases de datos SQLite en un solo archivo. También es compatible con el uso de múltiples archivos. Está diseñado para el esquema de fragmentación extrema: una base de datos SQLite por usuario.

Si está creando una base de datos separada para cada usuario, parece que no está estableciendo relaciones ... entonces, ¿por qué usar una base de datos relacional?

Estoy considerando esta misma arquitectura ya que básicamente quería usar las bases de datos SQLLIte del lado del servidor como copia de seguridad y copia de sincronización para clientes. Mi idea para consultar todos los datos es usar Sphinx para la búsqueda de texto completo y ejecutar trabajos de Hadoop desde volcados planos de todos los datos a Scribe y luego exponer los resultados como servicios web. Sin embargo, esta publicación me da una pausa para pensar, así que espero que la gente continúe respondiendo con su opinión.

Si sus datos son tan fáciles de fragmentar, ¿por qué no usar un motor de base de datos estándar y, si escala lo suficientemente grande como para que el DB se convierta en el cuello de botella, fragmente la base de datos, con diferentes usuarios en diferentes instancias? El efecto es el mismo, pero no estás utilizando decenas de pequeñas bases de datos.

En realidad, es probable que tenga al menos algunos datos compartidos que no pertenecen a un solo usuario, y que con frecuencia necesita acceder a los datos de más de un usuario. Sin embargo, esto causará problemas con cualquiera de los sistemas.

Tener una base de datos por usuario facilitaría la restauración de datos de usuarios individuales, por supuesto, pero como @John dijo, los cambios de esquema requerirían algo de trabajo.

No es suficiente para hacerlo difícil, pero es suficiente para que no sea trivial.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top