MongoDB y conjuntos de datos que no caben en la RAM, sin importar lo duro que empujes


12

Esto depende mucho del sistema, pero es casi seguro que escalaremos un acantilado arbitrario y nos meteremos en un problema real. Tengo curiosidad por saber qué tipo de reglas generales existen para una buena relación RAM a espacio en disco. Estamos planeando nuestra próxima ronda de sistemas, y debemos tomar algunas decisiones con respecto a la RAM, las SSD y la cantidad de cada uno de los nuevos nodos.

Pero ahora para algunos detalles de rendimiento!

Durante el flujo de trabajo normal de un solo proyecto ejecutado, MongoDB recibe un porcentaje muy alto de escrituras (70-80%). Una vez que llega la segunda etapa de la tubería de procesamiento, es de lectura extremadamente alta, ya que necesita deduplicar los registros identificados en la primera mitad del procesamiento. Este es el flujo de trabajo para el que está hecho "mantener su conjunto de trabajo en RAM", y estamos diseñando alrededor de esa suposición.

Todo el conjunto de datos se golpea continuamente con consultas aleatorias de fuentes derivadas del usuario final; Aunque la frecuencia es irregular, el tamaño suele ser bastante pequeño (grupos de 10 documentos). Dado que esto está orientado al usuario, las respuestas deben estar por debajo del umbral "aburrido ahora" de 3 segundos. Es mucho menos probable que este patrón de acceso esté en la memoria caché, por lo que es muy probable que se produzcan golpes de disco.

Un flujo de trabajo de procesamiento secundario es de alta lectura de ejecuciones de procesamiento anteriores que pueden tener días, semanas o incluso meses, y se ejecuta con poca frecuencia, pero aún debe ser rápido. Se accederá hasta el 100% de los documentos en la ejecución de procesamiento anterior. Sospecho que ninguna cantidad de calentamiento de caché puede ayudar con esto.

Tamaños de documentos acabados varían ampliamente, pero la mediana de tamaño es aproximadamente 8K.

La porción de alta lectura del procesamiento normal del proyecto sugiere fuertemente el uso de réplicas para ayudar a distribuir el tráfico de lectura. He leído en otra parte que un 1:10 RAM-GB a HD-GB es una buena regla general para discos lentos. Como estamos considerando seriamente el uso de SSD mucho más rápidos, me gustaría saber si hay una regla similar de pulgar para discos rápidos.

Sé que estamos usando Mongo de una manera en la que todo el caché realmente no va a volar, por eso estoy buscando formas de diseñar un sistema que pueda sobrevivir a ese uso. El conjunto de datos completo probablemente será la mayor parte de una tuberculosis dentro de medio año y seguirá creciendo.


Una pregunta difícil bien hecha.
gWaldo

Parece que probablemente va a tener problemas de bloqueo de escritura antes de que pueda sintonizar IO mucho, sinceramente. Si martilla la base de datos con escrituras, probablemente mantendrá bloqueos de escritura el tiempo suficiente para que las consultas se detengan, independientemente de qué tan rápido sea el IO subyacente. Algo así como Fusion IO puede reducir un poco el bloqueo de escritura, pero solo compra algo de tiempo, no es una solución real.
MrKurt

@MrKurt Parte de lo que estoy tratando de resolver es cuándo necesito fragmentar, además de lo robusto que puedo hacer los nodos de réplica individuales. Mi especificación provisional tiene una tarjeta SSD basada en PCIe involucrada.
sysadmin1138

Ah, lo tengo. Puede considerar fragmentar desde el principio, hacemos mucho fragmentación de un solo servidor. Le permite sortear el bloqueo de escritura y escalar efectivamente las escrituras a sus núcleos totales. Además, es fácil mover fragmentos entre servidores en un momento posterior.
MrKurt

Respuestas:


5

Esto va a ser un montón de pequeños puntos. Sin embargo, lamentablemente no hay una respuesta única a su pregunta.

MongoDB permite que el núcleo del sistema operativo maneje la administración de memoria. Además de arrojar tanta RAM como sea posible al problema, solo hay algunas cosas que se pueden hacer para 'administrar activamente' su Conjunto de trabajo.

Lo único que puede hacer para optimizar las escrituras es primero consultar ese registro (hacer una lectura), para que esté en la memoria de trabajo. Esto evitará los problemas de rendimiento asociados con el bloqueo global de todo el proceso (que se supone que se convertirá en per-db en v2.2)

No existe una regla estricta para la relación RAM vs SSD, pero creo que los IOPS sin procesar de los SSD deberían permitirle ir con una relación mucho más baja. Fuera de mi cabeza, 1: 3 es probablemente el más bajo con el que quieres ir. Pero dados los costos más altos y las capacidades más bajas, es probable que deba mantener esa proporción baja de todos modos.

Con respecto a 'Fases de escritura vs lectura', ¿estoy leyendo correctamente que una vez que se escribe un registro, rara vez se actualiza ("insertado")? Si ese es el caso, puede valer la pena alojar dos grupos; el clúster de escritura normal y el clúster de lectura optimizada para datos "antiguos" que no se han modificado en [X período de tiempo] . Definitivamente habilitaría la lectura esclava en este clúster. (Personalmente, lo manejaría al incluir un valor de fecha modificada en los documentos objeto de su base de datos).

Si tiene la capacidad de realizar pruebas de carga antes de ingresar a Prod, realice un excelente seguimiento. MongoDB se escribió con el supuesto de que a menudo se implementaría en máquinas virtuales (sus sistemas de referencia están en EC2), por lo que no tenga miedo de compartirlas en máquinas virtuales.


Durante el procesamiento, se crea un apéndice de documento inicial y luego se actualiza continuamente por varias sub-etapas en la primera parte del procesamiento. Hemos sopesado la posibilidad de hacer algo de relleno manual en la creación inicial para reducir la cantidad de extensión que estamos haciendo, pero nuestro porcentaje actual de bloqueo de escritura es felizmente bajo.
sysadmin1138

El consejo de leer un registro antes de escribirlo para llevarlo a la RAM no es un buen consejo. Desde 2.0 (mediados de 2011), MongoDB ha tenido rendimientos si los datos a los que se accede no están en la RAM, por lo que solo está causando una lectura adicional y un viaje de ida y vuelta adicional al servidor sin ninguna buena razón si lo hace, ya que el bloqueo no No será retenido por esa duración de todos modos.
Asya Kamsky

13

Esto pretende ser una adición a las otras respuestas publicadas aquí, que analizan muchos de los elementos relevantes que se deben considerar aquí. Sin embargo, hay otro factor, a menudo pasado por alto, cuando se trata de la utilización eficiente de RAM en un sistema de tipo de acceso aleatorio: lectura anticipada.

Puede verificar la configuración actual de readahead (en Linux) ejecutando blockdev --report(generalmente requiere privilegios sudo / root). Esto imprimirá una tabla con una fila para cada dispositivo de disco. La columna RA contiene el valor de readahead. Ese valor es el número de sectores de 512 bytes (a menos que el tamaño del sector no sea el predeterminado; tenga en cuenta que al momento de escribir esta publicación, incluso los discos que tienen tamaños más grandes son tratados como sectores de 512 bytes por el núcleo) que se leen en cada acceso al disco

Puede establecer la configuración de lectura anticipada para un dispositivo de disco dado ejecutando:

blockdev --setra <value> <device name>

Cuando utilice un sistema RAID basado en software, asegúrese de configurar el encabezado de lectura en cada dispositivo de disco, así como en el dispositivo que corresponde al controlador RAID.

¿Porque es esto importante? Bueno, readahead usa el mismo recurso que MongoDB está tratando de usar para optimizar sus lecturas para acceso secuencial: RAM. Cuando estás haciendo lecturas secuenciales en discos giratorios (o dispositivos que se comportan de alguna manera como discos giratorios de todos modos, EBS te estoy mirando), recuperar los datos cercanos en la RAM puede aumentar el rendimiento de forma masiva, ahorrarte búsquedas y una alta configuración de lectura anticipada en El entorno adecuado puede obtener algunos resultados impresionantes.

Para un sistema como MongoDB donde su acceso generalmente será aleatorio a través de un conjunto de datos, esto es solo un desperdicio de memoria que se usa mejor en otros lugares. El sistema, que como se menciona en otra parte administra la memoria para MongoDB también, asignará un trozo de memoria para leerlo cuando se solicite y, por lo tanto, dejará menos RAM para que MongoDB lo use de manera efectiva.

Elegir el tamaño de lectura correcto es complicado y depende de su hardware, la configuración, el tamaño del bloque, el tamaño de la banda y los datos en sí. Si se cambia a SSD, por ejemplo, querrá una configuración baja, pero qué tan baja dependerá de los datos.

Para explicar: desea asegurarse de que la lectura anticipada sea lo suficientemente alta como para extraer un solo documento completo y no tener que volver al disco. Tomemos su tamaño medio mencionado de 8k, ya que los sectores en el disco son generalmente de 512 bytes, se necesitarían 16 accesos de disco para leer en todo el documento sin lectura previa. Si tuviera una lectura anticipada de 16 sectores o más, leería todo el documento con solo un viaje al disco.

En realidad, dado que los segmentos de índice de MongoDB son 8k, nunca querrá establecer el encabezado de lectura por debajo de 16 de todos modos, o necesitará 2 accesos de disco para leer en un segmento de índice. Una buena práctica general es comenzar con su configuración actual, reducirla a la mitad, luego reevaluar su utilización de RAM e IO y continuar desde allí.


1
Información valiosa que definitivamente será útil una vez que tengamos algo de hardware en casa. ¡Gracias!
sysadmin1138

3

Debería considerar el uso de réplicas para consultas de usuarios finales y realizar su flujo de trabajo en otras máquinas.

Usando su regla general de 1:10, está buscando aproximadamente 128 GB de RAM para 1 TB de almacenamiento en disco; Si bien algunos SSD asequibles hoy en día afirman alcanzar> 60K IOPS, los números del mundo real pueden diferir bastante, así como si está utilizando RAID con sus SSD o no, y si lo está, la tarjeta RAID también es extremadamente importante .

En el momento de esta publicación, pasar de 128 GB de RAM DDR3 ECC a 256 GB parece ser alrededor de 2000 $ extra en un servidor Intel de 1U, y esto le dará una proporción de 1: 5 con 1 TB de datos, lo que creo que sería una Aún mejor relación. Si necesita que su carga de trabajo termine lo más rápido posible, definitivamente más RAM ayudará, pero ¿es realmente tan urgente?

También necesitará hacer algunos ajustes al sistema de archivos, algo así como "noatime, data = writeback, nobarrier" en ext4, y es posible que deba hacer algunos ajustes en la configuración del kernel para obtener el máximo rendimiento posible de su sistema.

Si va a utilizar RAID, RAID-10 será una muy buena opción, y con el controlador RAID adecuado ofrecerá un gran aumento de rendimiento, pero reducirá a la mitad su espacio disponible. También puede buscar RAID50 si desea un aumento de rendimiento decente sin reducir a la mitad su espacio disponible. El riesgo de ejecutar un RAID es que ya no tiene acceso a TRIM en sus unidades, lo que significa que de vez en cuando necesita mover sus datos, dividir el RAID, RECORTAR las unidades y recrear el RAID.

En última instancia, debe decidir cuánta complejidad desea, cuánto dinero desea gastar y con qué rapidez desea que se procese su carga de trabajo. También evaluaría si MongoDB es la base de datos ideal para usar, ya que aún podría usar Mongo para consultas de usuarios finales que necesitan respuestas rápidas, pero usa algo más para procesar sus datos, que no necesita estar listo en unos segundos , y también puede permitirle distribuir su carga de trabajo en varias máquinas con más facilidad.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.