database - tutorial - Auto sharding postgresql?
sharding mongodb tutorial (5)
Tengo un problema en el que necesito cargar una gran cantidad de datos (más de 5 mil millones de filas) en una base de datos muy rápidamente (idealmente menos de 30 minutos, pero más rápido es mejor), y recientemente se me sugirió buscar en postgresql (fallé con mysql y estaba mirando a hbase / cassandra). Mi configuración es que tengo un clúster (actualmente 8 servidores) que genera una gran cantidad de datos, y estaba pensando en ejecutar bases de datos localmente en cada máquina en el clúster que escribe rápidamente localmente y luego al final (o durante la generación de datos) los datos son fusionados juntos. Los datos no están en ningún orden, por lo que no me importa en qué servidor específico esté encendido (siempre que esté allí).
Mis preguntas son, ¿hay buenos tutoriales o lugares para aprender sobre el shard automático de PostgreSQL (encontré resultados de firmas como sykpe haciendo auto sharding pero no tutoriales, quiero jugar con esto yo mismo)? ¿Es lo que estoy tratando de hacer posible? Debido a que los datos no están en el orden en que iba a utilizar el número de identificación de incremento automático, ¿causará un conflicto si los datos se combinan (esto ya no es un gran problema)?
Actualización: la idea de Frank a continuación eliminó el problema de conflicto de auto-incremento que estaba preguntando. La pregunta es básicamente ahora, ¿cómo puedo aprender acerca de la fragmentación automática y sería compatible con cargas distribuidas de datos a múltiples servidores?
Aquí hay algunas cosas que podrían ayudar:
El DB en cada servidor debe tener una pequeña tabla de metadatos con las características únicas de ese servidor. Como qué servidor es; Los servidores pueden ser numerados secuencialmente. Aparte del contenido de esa tabla, probablemente sea conveniente tratar de mantener el esquema en cada servidor lo más similar posible.
Con miles de millones de filas querrás los ID de bigint (o UUID o similares). Con los bigints, podría asignar un rango generoso para cada servidor y configurar su secuencia para usarlo. Por ejemplo, el servidor 1 obtiene 1..1000000000000000, el servidor 2 obtiene 1000000000000001 a 2000000000000000, etc.
Si los datos son puntos de datos simples (como una lectura de temperatura de exactamente 10 instrumentos por segundo), puede obtener ganancias de eficiencia si los almacena en una tabla con columnas
(time timestamp, values double precision[])
lugar de los más correctos(time timestamp, instrument_id int, value double precision)
. Esta es una desnormalización explícita en beneficio de la eficiencia. (Hice un blogged sobre mi propia experiencia con este esquema).
Lo siento, no tengo un tutorial a la mano, pero aquí hay un resumen de una posible solución:
- Cargue uno ocho de sus datos en una instancia de PG en cada uno de los servidores
- Para una velocidad de carga óptima, no use inserciones sino el método de COPY
- Cuando se cargan los datos, no combine las ocho bases de datos en una sola. En su lugar, use plProxy para iniciar una sola declaración para consultar todas las bases de datos a la vez (o la correcta para satisfacer su consulta)
Como ya se señaló, las claves pueden ser un problema. El uso de secuencias o uuid no superpuestas o números de secuencia con un prefijo de cadena no debería ser demasiado difícil de resolver.
Debe comenzar con una prueba de COPIA en uno de los servidores y ver qué tan cerca de su meta de 30 minutos puede obtener. Si sus datos no son importantes y tiene una versión reciente de Postgresql, puede intentar usar tablas no registradas que deberían ser mucho más rápidas (pero no a prueba de fallos). Suena como un proyecto divertido, buena suerte.
Podría usar mySQL, que admite la fragmentación automática en un clúster.
Primero: ¿Realmente necesita insertar los datos generados desde su clúster directamente en una base de datos relacional? No te importa fusionarlo al final, de todos modos, ¿por qué molestarse en insertarlo en una base de datos? En su posición, haría que los nodos de su clúster escriban archivos planos, probablemente datos CSV gzip''d. Luego importaría de forma masiva y fusionaba esos datos utilizando una herramienta como pgbulkload.projects.postgresql.org .
Si necesita insertarlo directamente en una base de datos relacional: Eso es (parte de) para lo que son PgPool-II y (especialmente) PgBouncer . Configure PgBouncer para equilibrar la carga en diferentes nodos y debería estar bastante ordenado.
Tenga en cuenta que PostgreSQL es una base de datos transaccional con sólidas garantías de durabilidad de los datos. Eso también significa que si lo usa de manera simplista, hacer muchas escrituras pequeñas puede ser lento. Debe considerar qué compensaciones está dispuesto a hacer entre la durabilidad de los datos, la velocidad y el costo del hardware.
En un extremo, cada INSERT
puede ser su propia transacción que se confirma de forma síncrona en el disco antes de devolverlo correctamente. Esto limita la cantidad de transacciones por segundo a la cantidad de fsync () que puede hacer su subsistema de disco, que a menudo es solo en decenas o cientos por segundo (sin el controlador RAID con batería de respaldo). Este es el valor predeterminado si no hace nada especial y si no envuelve sus INSERT
en un BEGIN
y COMMIT
.
En el otro extremo, dices "Realmente no me importa si pierdo todos estos datos" y utilizas tablas no registradas para tus inserciones. Básicamente, esto le da permiso a la base de datos para desechar sus datos si no puede garantizar que esté bien, por ejemplo, después de una falla del sistema operativo, falla de la base de datos, pérdida de energía, etc.
El punto medio es donde probablemente querrás estar. Esto implica una combinación de compromisos asíncronos , compromisos de grupo ( commit_delay y commit_siblings ), inserciones por lotes en grupos envueltos en BEGIN
y END
explícitos, etc. Todas estas cosas intercambian la durabilidad de los datos frente a la velocidad.
Para inserciones masivas rápidas también debe considerar la inserción en tablas sin ningún índice, excepto una clave principal. Tal vez ni siquiera eso. Cree los índices una vez que sus inserciones masivas estén hechas. Esto será mucho más rápido.
Usa citus para el auto sharding de PostgreSQL. También este enlace es útil.