Resumen
¿Cómo puede configurar Linux tanto para leer desde un disco / sistema de archivos local como para escribir en un recurso compartido de red al mismo tiempo, en lugar de leer mientras no hay datos en la red, y luego enviar esos datos a través de la red mientras el disco local está ¿ocioso?
Es mucho más rápido leer y escribir al mismo tiempo en lugar de solo realizar una operación y luego la otra de manera alterna.
Detalles
Estoy transfiriendo una gran cantidad de datos de discos locales en una máquina Linux a un dispositivo NAS.
Estoy usando rsync
para copiar, básicamente, /srv/data
en /mnt/nas
que es un soporte de CIFS.
Comenzó bien, leyendo a 100 MB / seg y escribiendo en el NAS a 100 MB / seg (límite de la red de gigabits), con lectura y escritura simultáneamente.
Sin embargo, ahora, unas horas más tarde, descubro que está leyendo desde el disco local, luego detengo la lectura mientras escribe en el NAS, luego, cuando no hay más datos para escribir en el NAS, reanuda la lectura desde el disco de nuevo. La red está inactiva mientras se lee el disco, y el disco está inactivo mientras la red está en uso.
No hace falta decir que leer 200 MB y luego escribir 200 MB lleva mucho más tiempo que leer y escribir esos 200 MB al mismo tiempo.
¿Cómo puedo configurar el núcleo de modo que se adhiera al comportamiento anterior de leer y escribir al mismo tiempo, en lugar de alternar entre leer y escribir, realizando solo una operación a la vez?
Algunas observaciones: cuando el disco local lee a más de 100 MB / seg, todo parece suceder en paralelo muy bien, pero una vez que el disco se ralentiza (parece que ahora solo va a 20 MB / seg por alguna razón) es cuando esta lectura / escritura El cambio parece suceder.
También puedo ejecutar sync
manualmente cada pocos segundos para que las escrituras sucedan en paralelo con las lecturas (aunque obviamente a velocidades reducidas), sin embargo, poner sync
un while
bucle para que se ejecute cada cinco segundos no parece ser la solución correcta ...
El núcleo parece almacenar en caché aproximadamente 1 GB de datos y luego escribirlo en la red lo más rápido posible, lo cual está bien, pero no entiendo por qué el disco lento debe dejar de leerse mientras los datos se envían a través de la red. red.
Respuestas:
Después de más investigación, parece que este problema está menos relacionado con el kernel y más sobre cómo
rsync
interactúan CIFS.Por lo que puedo entender, lo que está sucediendo es que cuando
rsync
cierra el archivo de destino, CIFS (y probablemente cualquier sistema de archivos de red) asegura que el archivo esté completamente enjuagado y escrito en el disco remoto antes de queclose
regrese la llamada al sistema. Esto es para asegurar a cualquier aplicación que una vez que la operación de cierre se complete con éxito, el archivo se haya guardado por completo y no exista riesgo de errores adicionales que puedan causar la pérdida de datos.Si esto no se hiciera, entonces sería posible que una aplicación cierre un archivo, salga pensando que la operación de guardar fue exitosa, y luego (tal vez debido a un problema de red) los datos no pudieron escribirse, pero para entonces es demasiado tarde para que la aplicación haga algo al respecto, como preguntarle al usuario si desea guardar el archivo en otro lugar.
Este requisito significa que cada vez que
rsync
termine de copiar un archivo, todo el búfer de disco debe vaciarse en la red antes dersync
poder continuar leyendo el siguiente archivo.Una solución alternativa es montar el recurso compartido CIFS con la opción
cache=none
que deshabilita esta función y hace que todas las E / S vayan directamente al servidor. Esto elimina el problema y permite que las lecturas y escrituras se ejecuten en paralelo, sin embargo, un inconveniente de esta solución es que el rendimiento es algo menor. En mi caso, la velocidad de transferencia de red cae de 110 MB / seg a 80 MB / seg.Esto puede significar que si está copiando archivos grandes, el rendimiento puede ser mejor con el comportamiento alternativo de lectura / escritura. Con muchos archivos más pequeños, deshabilitar el caché dará como resultado menos descargas de caché cada vez que se cierre un archivo, por lo que el rendimiento puede aumentar allí.
Parece que
rsync
necesita una opción para cerrar sus identificadores de archivo en otro subproceso, por lo que puede comenzar a leer el siguiente archivo mientras el último todavía está enjuagado.EDITAR: He confirmado que
cache=none
definitivamente ayuda cuando se transfieren muchos archivos pequeños (lo lleva de 10 MB / seg hasta 80 MB / seg) pero cuando se transfieren archivos grandes (1 GB +) secache=none
reduce la transferencia de 110 MB / seg a los mismos 80 MB / seg. Esto sugiere que la transferencia lenta desde muchos archivos pequeños tiene menos que ver con la búsqueda del disco de origen, y más con tener tantas descargas de caché de todos los archivos pequeños.fuente
rsync
no leer el archivo en un hilo diferente (en realidad, proceso diferente) porque está diseñado de modo que una copia dersync
se ejecuta en cada lado de la red, a pesar de que en su caso ambas copias están en el mismo lado (y el sistema de archivos se esconde la hecho de que hay una red). Supongo que no ayuda, porque el proceso del lector llena muy rápidamente la tubería mientras el proceso del escritor se bloquea en unclose()
.rsync
funcionaría mejor si estuviera usandorsync
el cable, no CIFS.rsync
en el NAS sería usar arsync
través de la red (comorsync -a files localhost:/dest/path
) mientras se introduce artificialmente un enorme búfer (como megabytes múltiples, al menos) en las conexiones de red. No estoy seguro de cuál sería el mejor truco para hacerlo.rsync
en la caja NAS también solucionaría el problema. Sin embargo, es un poco más complejo (permisos NAS extraños, tengo que soltar enlaces simbólicos, etc.) pero creo que si tuviera un poco más de datos para copiar, valdría la pena invertir tiempo en hacerlo.dump(8)
en un NAS montado sobre NFS. En ese momento, diagnostiqué que el problema estaba maximizando la CPU en el NAS, debido al efecto combinado del servidor NFS y un firewall que se ejecutaba en el NAS (la caja no estaba rooteada y el firewall no podía desactivarse por completo desde La interfaz web). El problema desapareció cuando reemplazamos el NAS con una PC vieja. FWIW