database - Sharding extremo: una base de datos SQLite por usuario
architecture scalability (8)
Estoy considerando esta misma arquitectura, ya que básicamente quería utilizar las bases de datos SQLLIte del lado del servidor como copia de respaldo y sincronización para los clientes. Mi idea para realizar consultas en todos los datos es utilizar Sphinx para la búsqueda de texto completo y ejecutar trabajos de Hadoop desde volcados planos de todos los datos hasta Scribe y luego exponer los resultados como servidores 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.
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 mucho en el futuro, por lo que me preocupa la escalabilidad.
En lugar de usar una base de datos MySQL / InnoDB centralizada y luego particionarla cuando llegue ese 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 pequeño archivo de base de datos de cada usuario en una ubicación remota una vez al día.
El aumento de escala será tan fácil como agregar discos duros adicionales para almacenar los nuevos archivos.
Cuando la aplicación crece más allá de un único servidor, puedo vincular los servidores al nivel del sistema de archivos usando GlusterFS y ejecutar la aplicación sin cambios, o configurar un sistema de proxy SQLite simple que permita a cada servidor manipular archivos sqlite en servidores adyacentes.
Los problemas de simultaneidad serán mínimos porque cada solicitud HTTP solo tocará uno o dos archivos de base de datos a la vez, de miles, y solo bloques de SQLite en lecturas de todos modos.
Apuesto a que este enfoque permitirá a mi aplicación escalar con gracia y admitir muchas características geniales y únicas . ¿Estoy apostando mal? ¿Me estoy perdiendo algo?
ACTUALIZACIÓN Decidí ir con una solución menos extrema, que funciona bien hasta el momento. Estoy usando una cantidad fija de fragmentos: 256 bases de datos sqlite, para ser precisos. Cada usuario se asigna y se vincula a un fragmento aleatorio mediante una función de hash simple.
La mayoría de las características 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 están almacenados en caché en la memoria RAM. ¡Creo que puedo vivir con eso!
ACTUALIZACIÓN 2.0 Transmití la aplicación a MySQL / InnoDB y pude obtener el mismo rendimiento para las solicitudes regulares, pero para esa solicitud que requiere acceso a fragmentos, innodb es 4-5 veces más rápido. Por esta razón, y por otra razón, estoy abandonando esta arquitectura, pero espero que alguien en algún lugar encuentre un uso para ella ... gracias.
Me parece una pesadilla de mantenimiento. ¿Qué sucede cuando el esquema cambia en todos esos DB?
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?
Si sus datos son tan fáciles de fragmentar, ¿por qué no simplemente utiliza un motor de base de datos estándar, y si escala lo suficientemente grande como para que el DB se convierta en un 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 ningún usuario, y probablemente necesite 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 los datos de los usuarios individuales, por supuesto, pero como dijo , los cambios de esquema requerirían algo de trabajo.
No es suficiente para dificultarlo, pero es suficiente para que no sea trivial.
Un posible problema es que tener una base de datos para cada usuario utilizará el espacio de disco y la RAM de manera muy ineficiente, ya medida que crezca la base de usuarios, el beneficio de utilizar 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 constan de 1024 bases de datos SQLite que albergan hasta 100 usuarios cada una . Esto será más eficiente que el enfoque DB por usuario, porque los datos se empacan de manera más eficiente. Y más ligero que el enfoque del servidor de base de datos Innodb, porque estamos usando Sqlite.
La simultaneidad también será bastante buena, pero las consultas serán menos elegantes (shard_id yuckiness). ¿Qué piensas?
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. Es compatible con la combinación de 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 sharding extremo: una base de datos SQLite por usuario.
El lugar donde esto fracasará es si tiene que hacer lo que se llama "caminar por el fragmento", que consiste en descubrir toda la información de un grupo de usuarios diferentes. Ese tipo particular de "consulta" tendrá que hacerse programáticamente, preguntando a cada una de las bases de datos SQLite por turno, y muy probablemente sea 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 que este sea un diseño eficaz es saber cómo se utilizarán los datos y si los datos de una persona interactuarán. con datos de otro (en su contexto).
También es posible que tenga que tener cuidado con los recursos del sistema de archivos (SQLite es genial, increíble, rápido, etc.), pero obtiene algunos beneficios de almacenamiento en caché y escritura cuando utiliza una "base de datos estándar" (es decir, MySQL, PostgreSQL, etc.) está diseñado En su diseño propuesto, se perderá algo de eso.