¿Cuál es la filosofía detrás de retrasar la escritura de datos en el disco?


72

En Linux, una ejecución finalizada de un comando como cpo ddno significa que los datos se han escrito en el dispositivo. Uno tiene que, por ejemplo, llamar synco invocar la función "Quitar con seguridad" o "Expulsar" en la unidad.

¿Cuál es la filosofía detrás de este enfoque? ¿Por qué no se escriben los datos de una vez? ¿No hay peligro de que la escritura falle debido a un error de E / S?


16
Recuerde que las llamadas al sistema de lectura y escritura pueden funcionar con un byte a la vez, pero las unidades de disco solo pueden leer o escribir bloques de tamaño fijo. La sobrecarga del byte a la vez I / O sería intolerable sin almacenamiento en búfer. Con el almacenamiento en búfer, es soportable.
Jonathan Leffler

Respuestas:


47

¿Cuál es la filosofía detrás de este enfoque?

Eficiencia (mejor uso de las características del disco) y rendimiento (permite que la aplicación continúe inmediatamente después de una escritura).

¿Por qué no se escriben los datos de una vez?

La principal ventaja es que el sistema operativo es libre de reordenar y fusionar operaciones de escritura contiguas para mejorar su uso de ancho de banda (menos operaciones y menos búsquedas). Los discos duros funcionan mejor cuando se solicita una pequeña cantidad de operaciones grandes, mientras que las aplicaciones tienden a necesitar una gran cantidad de operaciones pequeñas. Otra optimización clara es que el sistema operativo también puede eliminar todas las escrituras excepto la última cuando el mismo bloque se escribe varias veces en un corto período de tiempo, o incluso eliminar algunas escrituras todas juntas si el archivo afectado se ha eliminado mientras tanto.

Estas escrituras asincrónicas se realizan después de que la writellamada del sistema ha regresado. Esta es la segunda ventaja más visible para el usuario. Las escrituras asincrónicas aceleran las aplicaciones, ya que son libres de continuar su trabajo sin esperar a que los datos estén realmente en el disco. El mismo tipo de almacenamiento en búfer / almacenamiento en caché también se implementa para operaciones de lectura en las que los bloques de lectura recientes o frecuentes se retienen en la memoria en lugar de leerse nuevamente desde el disco.

¿No hay peligro de que la escritura falle debido a un error de E / S?

No necesariamente. Eso depende del sistema de archivos utilizado y la redundancia en el lugar. Un error de E / S puede ser inofensivo si los datos se pueden guardar en otro lugar. Los sistemas de archivos modernos como ZFS se auto curan de bloques de disco defectuosos. Tenga en cuenta también que los errores de E / S no bloquean los sistemas operativos modernos. Si ocurren durante el acceso a los datos, simplemente se informan a la aplicación afectada. Si ocurren durante el acceso a metadatos estructurales y ponen en riesgo el sistema de archivos, podría volverse a montar como de solo lectura o volverse inaccesible.

También existe un ligero riesgo de pérdida de datos en caso de un bloqueo del sistema operativo, un corte de energía o una falla de hardware. Esta es la razón por la cual las aplicaciones que deben estar 100% seguras de que los datos están en el disco (por ejemplo, bases de datos / aplicaciones financieras) están haciendo escrituras sincrónicas menos eficientes pero más seguras. Para mitigar el impacto en el rendimiento, muchas aplicaciones aún usan escrituras asíncronas, pero eventualmente las sincronizan cuando el usuario guarda explícitamente un archivo (por ejemplo, vim, procesadores de texto).

Por otro lado, una gran mayoría de usuarios y aplicaciones no necesitan ni les importa la seguridad que proporcionan las escrituras síncronas. Si hay un choque o un corte de energía, el único riesgo a menudo es perder en el peor de los últimos 30 segundos de datos. A menos que haya una transacción financiera involucrada o algo similar que implique un costo mucho mayor que 30 segundos de su tiempo, la enorme ganancia en el rendimiento (que no es una ilusión sino muy real), las escrituras asincrónicas están permitiendo superar en gran medida el riesgo.

Finalmente, las escrituras sincrónicas no son suficientes para proteger los datos escritos de todos modos. Si su aplicación realmente necesita asegurarse de que sus datos no puedan perderse, pase lo que pase, la replicación de datos en múltiples discos y en múltiples ubicaciones geográficas debe implementarse para resistir desastres como incendios, inundaciones, etc.


Además del costo, considere si se ha hecho algo que se base en que se hayan guardado los datos. Si estoy escribiendo mi novela, ahorrando secuencialmente, y un corte de energía significa que pierdo 30 segundos de trabajo, entonces, independientemente del valor de esos 30 segundos, al menos me recupero a un estado que realmente ocurrió durante el proceso de escritura , y puedo reiniciar desde allí. Por otro lado, si presiono "guardar" y luego tacho algo de mi lista de tareas de papel en mi escritorio, cuando me recupero tengo una inconsistencia entre mi disco duro y mi papel. Esto es generalmente más difícil de reanudar desde ...
Steve Jessop

1
... así que, como usuario normal, es posible que desee sincronizar el sistema de archivos antes de tachar "terminar de escribir mi novela" de mi lista de tareas pendientes, para asegurarme de que no creo haber hecho algo que realmente falla. Y esta es la razón por la cual las bases de datos y similares necesitan escrituras sincrónicas: incluso si pierden datos, deben mantener la coherencia.
Steve Jessop

1
@SteveJessop Estoy de acuerdo con tu ejemplo, pero no espero que un usuario casual se sincronice manualmente. Si el editor solía escribir la preciosa novela no llama a fsync o similar cuando se guarda el documento, este es un error que se debe corregir , por ejemplo, bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/817326 . Usaría vi (vim) para escribir el mío, vim llama a fsync en save de forma predeterminada.
jlliagre

59

Simplemente da una ilusión de velocidad a los programas que en realidad no tienen que esperar hasta que se complete una escritura. Monte sus sistemas de archivos en modo de sincronización (que le proporciona sus escrituras instantáneas) y vea qué tan lento es todo.

A veces los archivos existen solo temporalmente ... un programa hace un poco de trabajo y elimina el archivo justo después de que el trabajo está hecho. Si retrasó esas escrituras, podría salirse con la suya sin haberlas escrito nunca.

¿No hay peligro de que la escritura falle debido a un error de E / S?

Oh absolutamente En tal caso, generalmente todo el sistema de archivos entra en modo de solo lectura, y todo es horrible. Pero eso rara vez sucede, no tiene sentido perder las ventajas de rendimiento en general.


Ciertos controladores de HDD tienen batería de respaldo, por lo que en caso de falla de energía, los datos no confirmados se conservan en el controlador hasta que se restablezca la energía. Eso permite el uso en aplicaciones de bases de datos donde perder datos no es una opción.
strattonn

Linux almacena datos aún no escritos en RAM, no en HDD. HDD también tiene su propio caché.
Barafu Albino

Sería bastante conveniente si un archivo abierto por un proceso se sincronizara cuando el proceso se cierre. Esto no afectaría el proceso en sí, pero sería simplificar los scripts de shell y similares (que ahora tienen que sincronizar todo un sistema de archivos)
MSalters

14
Eso es más que una ilusión. Las escrituras asincrónicas mejoran el rendimiento general de las aplicaciones.
jlliagre

44
@frostschutz: más allá de los archivos existentes solo temporalmente, también existe el hecho de que algunas áreas de los archivos se reescriben una y otra vez.
Matthieu M.

26

La E / S asincrónica y amortiguada estaba en uso antes de Linux e incluso antes de Unix. Unix lo tenía, y también todos sus retoños.

Esto es lo que Ritchie y Thompson escribieron en su artículo de CACM The UNIX Time-Sharing System :

Para el usuario, tanto la lectura como la escritura de archivos parecen ser síncronas y sin búfer. Es decir, inmediatamente después del regreso de una llamada de lectura, los datos están disponibles y, por el contrario, después de una escritura, el espacio de trabajo del usuario puede reutilizarse. De hecho, el sistema mantiene un mecanismo de almacenamiento intermedio bastante complicado que reduce en gran medida el número de operaciones de E / S necesarias para acceder a un archivo.


En tu pregunta, también escribiste:

¿No hay peligro de que la escritura falle debido a un error de E / S?

Sí, la escritura puede fallar y es posible que el programa nunca lo sepa. Aunque nunca es bueno, los efectos de esto se pueden minimizar en los casos en que un error de E / S genera un pánico del sistema (en algunos sistemas operativos esto es configurable; en lugar de entrar en pánico, el sistema puede continuar ejecutándose pero el sistema de archivos afectado es desmontado o montado de solo lectura). Los usuarios pueden ser notificados de que los datos en ese sistema de archivos son sospechosos. Y una unidad de disco se puede monitorear proactivamente para ver si su lista de defectos aumentada está aumentando rápidamente, lo cual es una indicación de que la unidad está fallando.

BSD agregó la fsyncllamada al sistema para que un programa pudiera estar seguro de que sus datos de archivo se habían escrito completamente en el disco antes de continuar, y los sistemas Unix posteriores han proporcionado opciones para realizar escrituras sincrónicas. GNU dd tiene una opción conv=fsyncpara asegurarse de que todos los datos se hayan escrito antes de que salga el comando. Resulta útil al escribir en unidades flash extraíbles lentas, donde los datos almacenados en el búfer pueden tardar varios minutos en escribirse.

Otra fuente de corrupción de archivos es un apagado repentino del sistema, por ejemplo, por pérdida de energía. Prácticamente todos los sistemas actuales admiten una marca limpia / sucia en sus sistemas de archivos. El indicador se establece para limpiar cuando no hay más datos para escribir y el sistema de archivos está a punto de desmontarse, generalmente durante el apagado del sistema o mediante una llamada manual umount. Los sistemas generalmente se ejecutarán fsckal reiniciar si detectan que los sistemas de archivos no se cerraron limpiamente.


Supongamos que copiamos música de HDD a un disco externo. Puede suceder que la unidad externa esté corrupta y la escritura falle. Esto no provocaría que un programa se ejecute con datos erróneos. Y parece una exageración entrar en pánico ante un IO fallido en un dispositivo externo.
marmistrz

Buen punto. Modificaré mi respuesta.
Mark Plotnick

15

Muchas buenas respuestas, pero permítanme agregar otra cosa ... Recuerde que Unix es un sistema multiproceso y multiusuario, por lo que potencialmente muchos usuarios estarían intentando realizar operaciones de archivo (especialmente escrituras) en (casi) el Mismo tiempo. Con los viejos discos duros lentos, tal vez montados en la red, esto no solo llevaría tiempo (para lo cual los programas básicamente se bloquearían y los usuarios tendrían que esperar), sino que causaría mucho movimiento del cabezal de lectura / escritura del disco de ida y vuelta.

Entonces, en cambio, los archivos que esperaban ser escritos se mantuvieron en la memoria por un tiempo, y se ordenaron según dónde deberían terminar en el disco ... y cuando el búfer estaba lleno, o el demonio de sincronización de disco había esperado el número requerido de segundos (creo que usualmente fueron unos 30 segundos): todo el búfer se escribió en el disco "en orden", con el cabezal de escritura solo teniendo que hacer un movimiento de barrido continuo, escribiendo los archivos en el disco como fue ... en lugar de saltar por todo el lugar.

Por supuesto, con los discos rápidos de hoy en día, sin mencionar los dispositivos de estado sólido, la ganancia es mucho menor ... especialmente en un sistema Linux doméstico, donde solo hay un usuario trabajando a la vez, y solo con unos pocos programas.

De todos modos, la combinación de anticipar las lecturas leyendo (en el caché / búfer) más de lo que se solicitó, y clasificando los datos en espera de ser escritos, para que pudieran escribirse en "un solo movimiento", en realidad fue una muy buena idea. tiempo, especialmente en sistemas con mucha lectura y escritura por parte de muchos usuarios.


2
XFS ni siquiera decide dónde colocar los datos hasta la escritura. La asignación retrasada le da al asignador mucha más información para basar sus decisiones. Cuando se escribe un archivo por primera vez, no hay forma de saber si será un archivo 4k o un archivo 1G y aún en crecimiento. Si hay 10G de espacio libre contiguo en alguna parte, colocar el archivo 4k al comienzo no sirve de nada. Poner el archivo grande al comienzo de un gran espacio libre reduce la fragmentación.
Peter Cordes

13

No es específico de Linux, y se llama caché de página (que Linux hace bastante bien). Ver también http://linuxatemyram.com/ ; así que si se escribe un archivo, vuelva a leerlo unos segundos más tarde, a menudo no se necesita E / S de disco.

La principal ventaja es que en muchos sistemas, hay mucha RAM, y parte del núcleo puede ser utilizada como caché. Por lo tanto, algunas operaciones de archivos pueden aprovechar este almacenamiento en caché. Además, el tiempo de E / S de disco es mucho más lento (generalmente miles de veces para SDD y casi un millón de veces más lento para discos duros mecánicos) que la RAM.

El código de la aplicación puede dar pistas sobre este almacenamiento en caché: consulte, por ejemplo, posix_fadvise (2) y madvise (2)


8

Los platos giratorios son más lentos que la RAM. Usamos el almacenamiento en caché de lecturas / escrituras para 'ocultar' este hecho.

Lo útil de escribir IO es que no requiere que IO de disco ocurra de inmediato, a diferencia de una lectura, donde no puede devolver datos al usuario hasta que la lectura se complete en el disco.

Por lo tanto, las escrituras operan bajo una restricción de tiempo flexible: siempre que nuestro rendimiento sostenido no exceda el de nuestro disco, podemos ocultar muchas de las penalizaciones de rendimiento en un caché de escritura.

Y necesitamos escribir caché: los discos giratorios son muy lentos comparativamente. Pero para hacerlo, los tipos RAID modernos tienen una penalización significativa para la operación.

Un RAID 6, por ejemplo, para completar una escritura, IO debe:

  • Leer bloque de actualización
  • leer paridad1
  • leer paridad 2
  • escribir nuevo bloque
  • escribir paridad 1
  • escribir paridad 2

Por lo tanto, cada escritura es en realidad 6 operaciones de E / S, y particularmente cuando tiene discos lentos como grandes unidades SATA, esto se vuelve extremadamente costoso.

Pero hay una buena solución fácil: escribir en combinación. Si puede construir una escritura de 'franja completa' en un búfer, no necesita leer la paridad de su disco; puede calcularla en función de lo que tiene en la memoria.

Es muy deseable hacer esto, porque entonces ya no tienes amplificación de escritura. De hecho, puede terminar con una penalización de escritura menor que RAID 1 + 0.

Considerar:

RAID 6, 8 + 2 - 10 husillos.

8 bloques de datos consecutivos para escribir: calcule la paridad en la memoria caché y escriba un bloque en cada disco. 10 escrituras por 8, significa una penalización de escritura de 1.25. 10 discos de RAID 1 + 0 todavía tienen una penalización de escritura de 2 (porque tiene que escribir en cada submirror). Entonces, en este escenario, puede hacer que RAID 6 funcione mejor que RAID1 + 0. Sin embargo, en el uso en el mundo real, obtienes un poco más de un perfil IO mixto.

Por lo tanto, el almacenamiento en caché de escritura hace una gran diferencia en el rendimiento percibido de los conjuntos RAID: puede escribir a velocidad de RAM y tener una baja penalización de escritura, lo que mejora su rendimiento sostenido si lo hace.

Y si no lo hace, sufre el rendimiento lento de SATA, pero multiplíquelo por 6 y agregue cierta contención allí. Su SATA RAID-6 de 10 vías sin almacenamiento en caché de escritura sería un poco más rápido que una sola unidad sin RAID ... pero no mucho.

Sin embargo, se arriesga, como observa, la pérdida de energía significa la pérdida de datos. Puede mitigar esto mediante ciclos de descarga de caché, batería que respalde su caché o utilizando SSD u otros cachés no volátiles.


7

Ninguna de las otras respuestas mencionó la asignación tardía . XFS, ext4, BTRFS y ZFS lo usan. XFS lo ha estado usando desde antes de que existiera ext4, así que lo usaré como ejemplo:

XFS ni siquiera decide dónde colocar los datos hasta la escritura. La asignación retrasada le da al asignador mucha más información para basar sus decisiones. Cuando se escribe un archivo por primera vez, no hay forma de saber si será un archivo 4k o un archivo 1G y aún en crecimiento. Si hay 10G de espacio libre contiguo en alguna parte, colocar el archivo 4k al comienzo no sirve de nada. Poner el archivo grande al comienzo de un gran espacio libre reduce la fragmentación.


4

Todas las otras respuestas aquí son mínimas, en su mayoría correctas para el caso normal, y recomendaría leer cualquiera de ellas antes que la mía, pero usted mencionó dd y dd tiene un caso de uso típico que puede no involucrar el almacenamiento en caché de escritura. El almacenamiento en caché de escritura se implementa principalmente en el nivel del sistema de archivos. Los dispositivos sin formato no suelen almacenar en caché de escritura (los controladores de dispositivos múltiples, como raid o lvm, son otra bola de cera). Dado que dd se usa a menudo con dispositivos de bloque sin formato, proporciona bs y opciones relacionadas para permitir grandes escrituras para un mejor rendimiento en dispositivos sin formato. Esto no es tan útil cuando ambos puntos finales son archivos normales (aunque las escrituras grandes utilizan menos llamadas al sistema en este caso). El otro lugar común donde esto es particularmente visible es con el paquete mtools, que es una implementación del sistema de archivos fat del espacio de usuario. El uso de mtools con una unidad de disquete siempre se siente increíblemente lento, ya que las herramientas son completamente sincrónicas y las unidades de disquete son increíblemente lentas. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt.


44
Los dispositivos de bloque de Linux leen / escriben el caché de la página de forma predeterminada. Debe usarlo O_DIRECTsi desea omitir el caché. dd oflag=direct. IIRC, algunos dispositivos predeterminan la E / S directa en dispositivos de bloque. (Y requiere lectura / escritura de bloques alineados, lo que Linux no hace porque de todos modos solo está escribiendo el caché de página).
Peter Cordes

3

La filosofía es insegura por defecto.

Hay dos estrategias razonables y obvias posibles: vaciar las escrituras al disco inmediatamente o retrasar la escritura. UNIX eligió históricamente el último. Por lo tanto, obtenga seguridad, debe llamar fsyncdespués.

Sin embargo, puede especificar la seguridad por adelantado montando un dispositivo con opción sync, o por archivo abriéndolo con O_SYNC.

Recuerde que UNIX fue diseñado para expertos en informática. "Seguro por defecto" no fue una consideración. Seguridad significa E / S más lenta, y esos primeros sistemas realmente tenían E / S lenta, lo que hacía que la tasa de precios fuera muy alta. Desafortunadamente, ni UNIX ni Linux cambiaron a safe-be-default, a pesar de que este es un cambio sin interrupciones.


66
Una gran mayoría de las aplicaciones y usuarios no necesitan ni les importa la seguridad que proporcionarían las escrituras sincrónicas. Si hay un choque o un corte de energía, corre el riesgo de perder hasta los últimos 30 segundos de datos. Eso está bien con la mayoría de las personas a menos que haya una transacción financiera involucrada o algo similar que costará más de 30 segundos de nuestro tiempo. La configuración predeterminada de E / S sincrónicas habría implicado que todas las aplicaciones que tienen como objetivo la usabilidad tengan O_NOSYNC definido.
jlliagre

2

Cambia una pequeña cantidad de confiabilidad por un gran aumento en el rendimiento.

Supongamos, por ejemplo, un programa de compresión de video. Con escritura retrasada ("escribir de nuevo"):

  1. pasar 10 ms comprimiendo el marco
  2. emitir marco de escritura al disco
  3. espere 10 ms para que el disco confirme la escritura completa
  4. GOTO 1

Versus

  1. pasar 10 ms comprimiendo el marco
  2. emite un marco de escritura en el disco (se completa en segundo plano)
  3. GOTO 1

La segunda versión aparece el doble de rápido porque puede usar la CPU y el disco al mismo tiempo, mientras que la primera versión siempre está esperando uno u otro.

En general, desea una reescritura para las operaciones de transmisión y operaciones de archivos masivos, y la reescritura para bases de datos y aplicaciones similares.


1

En muchas aplicaciones, los dispositivos de almacenamiento estarán ocupados intermitentemente leyendo datos. Si un sistema siempre puede diferir las escrituras hasta el momento en que el dispositivo de almacenamiento no está ocupado leyendo datos, desde el punto de vista de una aplicación, las escrituras tardarán cero tiempo en completarse. Las únicas situaciones en las que las escrituras no serían instantáneas serían cuando:

  1. Los buffers de escritura se llenan hasta el punto de que no se pueden aceptar más solicitudes de escritura diferida hasta que las escrituras se completen realmente.

  2. Es necesario apagar o eliminar el dispositivo para el cual hay escrituras pendientes.

  3. Una aplicación solicita específicamente la confirmación de que una escritura se ha completado realmente.

De hecho, es solo debido a los requisitos anteriores que las escrituras siempre deben tener lugar. Por otro lado, generalmente no hay razón para no realizar ninguna escritura pendiente en momentos en que un dispositivo estaría inactivo, por lo que muchos sistemas las realizan en ese momento.


0

También hay esto:

Escribir "Hola, Joe Moe"
es más rápido que:
Escribir "Hola",
Escribir "Joe"
Escribir "Moe"

Y también:

Escribe "Hola, ¿cómo estás?"
es más rápido que:
Escribe "Hola, ¿qué pasa?"
Elimina eso
Escribe "Hola, ¿cómo estás?"
Elimina eso
Escribe "Hola, ¿cómo estás?"

Es mejor que ocurran modificaciones y agregaciones en la RAM que en el disco. La escritura en disco por lotes libera a los desarrolladores de aplicaciones de tales preocupaciones.

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.