{"id":98090,"date":"2020-10-24T02:42:38","date_gmt":"2020-10-24T00:42:38","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux"},"modified":"2020-11-18T00:58:48","modified_gmt":"2020-11-17T22:58:48","slug":"ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","title":{"rendered":"Almacenamiento de datos sostenible y API de archivos en Linux","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Yo, al investigar la persistencia del almacenamiento de datos en sistemas en la nube, decid\u00ed ponerme a prueba y asegurarme de que entiendo los conceptos b\u00e1sicos. Yo <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">comenc\u00e9 leyendo la especificaci\u00f3n NVMe<\/a><\/noindex> para entender cu\u00e1les son las garant\u00edas relacionadas con el almacenamiento persistente de datos (es decir, las garant\u00edas de que los datos estar\u00e1n disponibles despu\u00e9s de una falla del sistema) que nos ofrecen los discos NVMe. Mis principales conclusiones son las siguientes: se debe considerar que los datos est\u00e1n da\u00f1ados desde el momento en que se da la orden de escritura y hasta que se complete su escritura en el medio de informaci\u00f3n. Sin embargo, en la mayor\u00eda de los programas de escritura de datos, se utilizan tranquilamente llamadas al sistema.<\/p>\n<p>En este material, investigo los mecanismos de almacenamiento persistente de datos que proporcionan las API de archivos de Linux. Parece que todo deber\u00eda ser simple aqu\u00ed: el programa llama al comando <code>write()<\/code>, y despu\u00e9s de que este comando finaliza su trabajo, los datos deber\u00edan ser almacenados de forma segura en el disco. Pero <code>write()<\/code> solo copia los datos de la aplicaci\u00f3n en la cach\u00e9 del n\u00facleo, que se encuentra en la memoria RAM. Para forzar al sistema a escribir los datos en el disco, se deben usar algunos mecanismos adicionales.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/524172\/\"><img decoding=\"async\" alt=\"Almacenamiento de datos sostenible y API de archivos en Linux\" src=\"\/wp-content\/uploads\/2020\/10\/b974dcb9fc546cae03ade4f3d8f5dc25.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>En general, este material es un conjunto de notas sobre lo que aprend\u00ed en el tema que me interesa. Si quiero resumir lo m\u00e1s importante, dir\u00eda que para organizar un almacenamiento persistente de datos se debe utilizar el comando <code>fdatasync()<\/code> o abrir archivos con la bandera <code>O_DSYNC<\/code>. Si te interesa conocer en detalle qu\u00e9 sucede con los datos en el camino del c\u00f3digo de programa al disco, echa un vistazo a <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">esto<\/a><\/noindex> el art\u00edculo.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Las caracter\u00edsticas del uso de la funci\u00f3n write()<\/h2>\n<p>\nLlamada del sistema <code>write()<\/code> est\u00e1n definidas en el est\u00e1ndar <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/POSIX\">IEEE POSIX<\/a><\/noindex> como un intento de escribir datos en un descriptor de archivo. Despu\u00e9s de la finalizaci\u00f3n exitosa <code>write()<\/code> de la operaci\u00f3n, la lectura de datos debe devolver exactamente esos bytes que fueron escritos previamente, incluso si los datos est\u00e1n siendo accedidos desde otros procesos o hilos (<noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/write.html#tag_16_685_08\">aqu\u00ed<\/a><\/noindex> la secci\u00f3n correspondiente del est\u00e1ndar POSIX). <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/V2_chap02.html#tag_15_09_07\">Aqu\u00ed<\/a><\/noindex>, en la secci\u00f3n dedicada a la interacci\u00f3n de los hilos con operaciones de archivo convencionales, hay una nota que dice que si cada uno de los dos hilos llama a estas funciones, cada llamada debe ver o todas las consecuencias designadas que resultan de la ejecuci\u00f3n de la otra llamada, o no ver ninguna consecuencia en absoluto. Esto permite concluir que todas las operaciones de entrada\/salida de archivos deben mantener un bloqueo del recurso con el que trabajan.<\/p>\n<p>\u00bfSignifica esto que la operaci\u00f3n <code>write()<\/code> es at\u00f3mica? Desde un punto de vista t\u00e9cnico \u2014 s\u00ed. Las operaciones de lectura de datos deben devolver ya sea todo, o nada de lo que ha sido escrito mediante <code>write()<\/code>. Pero la operaci\u00f3n <code>write()<\/code>, de acuerdo con el est\u00e1ndar, no necesariamente debe completar escribiendo todo lo que se le propuso escribir. Se le permite escribir solo una parte de los datos. Por ejemplo, podemos tener dos hilos, cada uno de los cuales adjunta 1024 bytes a un archivo descrito por el mismo descriptor de archivo. Desde el punto de vista del est\u00e1ndar, es aceptable que el resultado de cada operaci\u00f3n de escritura solo pueda adjuntar un byte al archivo. Estas operaciones seguir\u00e1n siendo at\u00f3micas, pero despu\u00e9s de que se completen, los datos que escribieron en el archivo estar\u00e1n mezclados. <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/a\/42442926\/413438\">Aqu\u00ed<\/a><\/noindex> una discusi\u00f3n muy interesante sobre este tema en Stack Overflow.<\/p>\n<h2>Las funciones fsync() y fdatasync()<\/h2>\n<p>\nLa forma m\u00e1s sencilla de volcar datos en el disco es a trav\u00e9s de la llamada a la funci\u00f3n <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fsync.2.html\">fsync()<\/a><\/noindex>. Esta funci\u00f3n solicita al sistema operativo que transfiera todos los bloques modificados desde la cach\u00e9 al disco. Esto incluye todos los metadatos del archivo (tiempo de acceso, tiempo de modificaci\u00f3n del archivo, etc.). Creo que la necesidad de estos metadatos surge raramente, por lo que, si sabes que no son importantes para ti, puedes utilizar la funci\u00f3n <code>fdatasync()<\/code>. Hay <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fdatasync.2.html\">ayuda<\/a><\/noindex> en <code>fdatasync()<\/code> indica que durante la ejecuci\u00f3n de esta funci\u00f3n se guarda en disco un volumen de metadatos que es \"necesario para el correcto funcionamiento de las siguientes operaciones de lectura de datos\". Y esto es precisamente lo que preocupa a la mayor\u00eda de las aplicaciones.<\/p>\n<p>Uno de los problemas que puede surgir aqu\u00ed es que estos mecanismos no garantizan que se pueda encontrar el archivo despu\u00e9s de un posible fallo. En particular, al crear un nuevo archivo, es necesario llamar a <code>fsync()<\/code> para el directorio que lo contiene. De lo contrario, despu\u00e9s de un fallo, puede suceder que este archivo no exista. La raz\u00f3n de esto se debe a que en UNIX, debido al uso de enlaces duros, un archivo puede existir en varios directorios. Por lo tanto, al invocar <code>fsync()<\/code> no hay forma de que un archivo se entere de qu\u00e9 directorio espec\u00edfico tambi\u00e9n necesita ser volcado en el disco (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.quora.com\/When-should-you-fsync-the-containing-directory-in-addition-to-the-file-itself\">aqu\u00ed<\/a><\/noindex> se puede leer m\u00e1s sobre esto). Parece que el sistema de archivos ext4 es capaz <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/799807\/\">autom\u00e1ticamente<\/a><\/noindex> aplicar <code>fsync()<\/code> a los directorios que contienen los archivos correspondientes, pero en el caso de otros sistemas de archivos, esto puede no ser as\u00ed.<\/p>\n<p>Este mecanismo puede ser implementado de diferentes maneras en varios sistemas de archivos. Yo utilic\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/axboe\/blktrace.git\/tree\/README\">blktrace<\/a><\/noindex> para averiguar cu\u00e1les operaciones de disco se utilizan en los sistemas de archivos ext4 y XFS. Ambos emiten comandos de escritura en disco est\u00e1ndar tanto para el contenido de los archivos como para el registro del sistema de archivos, vac\u00edan la cach\u00e9 y finalizan el trabajo ejecutando una escritura FUA (Acceso forzado a la unidad, escritura de datos directamente en el disco, omitiendo la cach\u00e9) en el registro. Probablemente, hacen esto para confirmar el hecho de que se realiz\u00f3 la operaci\u00f3n. En discos que no soportan FUA, esto provoca dos vaciados de cach\u00e9. Mis experimentos mostraron que <code>fdatasync()<\/code> un poco m\u00e1s r\u00e1pido <code>fsync()<\/code>. Utilidad <code>blktrace<\/code> indica que <code>fdatasync()<\/code> generalmente escribe menos datos en el disco (en ext4 <code>fsync()<\/code> escribe 20 KiB, y <code>fdatasync()<\/code> \u2014 16 KiB). Adem\u00e1s, descubr\u00ed que XFS es un poco m\u00e1s r\u00e1pido que ext4. Y aqu\u00ed, con la ayuda de <code>blktrace<\/code> logr\u00e9 averiguar que <code>fdatasync()<\/code> vuelca menos datos al disco (4 KiB en XFS).<\/p>\n<h2>Situaciones ambiguas que surgen al usar fsync()<\/h2>\n<p>\nPuedo recordar tres situaciones ambiguas relacionadas <code>fsync()<\/code>, con las que me encontr\u00e9 en la pr\u00e1ctica.<\/p>\n<p>El primer caso ocurri\u00f3 en 2008. En ese momento, la interfaz de Firefox 3 \"se colgaba\" si se realizaba la escritura en disco de una gran cantidad de archivos. El problema resid\u00eda en que en la implementaci\u00f3n de la interfaz se utilizaba una base de datos SQLite para almacenar informaci\u00f3n sobre su estado. Despu\u00e9s de cada cambio en la interfaz, se llamaba a la funci\u00f3n <code>fsync()<\/code>, lo que daba buenas garant\u00edas de almacenamiento persistente de datos. En el sistema de archivos ext3 que se utilizaba entonces, la funci\u00f3n <code>fsync()<\/code> reinici\u00f3 el disco con todas las p\u00e1ginas \"sucias\" en el sistema, y no solo aquellas relacionadas con el archivo correspondiente. Esto significaba que un clic en el bot\u00f3n de Firefox pod\u00eda iniciar la escritura de megabytes de datos en el disco magn\u00e9tico, lo que pod\u00eda tardar muchos segundos. La soluci\u00f3n al problema, seg\u00fan entend\u00ed de <noindex><a rel=\"nofollow\" href=\"http:\/\/shaver.off.net\/diary\/2008\/05\/25\/fsyncers-and-curveballs\/\">esto<\/a><\/noindex> el material, consist\u00eda en trasladar el trabajo con la base de datos a tareas as\u00edncronas en segundo plano. Esto implica que antes en Firefox se implementaron requisitos m\u00e1s estrictos para la persistencia del almacenamiento de datos de lo que realmente era necesario, y las caracter\u00edsticas del sistema de archivos ext3 solo agravaron este problema.<\/p>\n<p>La segunda discrepancia ocurri\u00f3 en 2009. Entonces, despu\u00e9s de una falla en el sistema, los usuarios del nuevo sistema de archivos ext4 se encontraron con que muchos archivos reci\u00e9n creados ten\u00edan una longitud cero, mientras que no ocurri\u00f3 lo mismo con el sistema de archivos m\u00e1s antiguo ext3. En el p\u00e1rrafo anterior, mencion\u00e9 que ext3 volcaba demasiados datos al disco, lo que ralentizaba considerablemente el rendimiento <code>fsync()<\/code>. Para mejorar la situaci\u00f3n, en ext4 solo se vuelcan al disco aquellas p\u00e1ginas \"sucias\" que est\u00e1n relacionadas con un archivo espec\u00edfico. Y los datos de otros archivos permanecen en memoria durante mucho m\u00e1s tiempo que con ext3. Esto se hizo para mejorar el rendimiento (por defecto, los datos permanecen en este estado 30 segundos, se puede ajustar esto con <noindex><a rel=\"nofollow\" href=\"https:\/\/www.kernel.org\/doc\/Documentation\/sysctl\/vm.txt\">dirty_expire_centisecs<\/a><\/noindex>; <noindex><a rel=\"nofollow\" href=\"https:\/\/www.spinics.net\/lists\/linux-ext4\/msg68941.html\">aqu\u00ed<\/a><\/noindex> , se pueden encontrar materiales adicionales sobre esto). Esto implica que un gran volumen de datos puede perderse permanentemente tras un fallo. La soluci\u00f3n a este problema radica en utilizar <code>fsync()<\/code> en aplicaciones que necesitan garantizar la persistencia del almacenamiento de datos y maximizar su protecci\u00f3n contra las consecuencias de fallos. La funci\u00f3n <code>fsync()<\/code> funciona con ext4 mucho m\u00e1s eficazmente que con ext3. La desventaja de este enfoque es que, al igual que antes, ralentiza la realizaci\u00f3n de algunas operaciones, como la instalaci\u00f3n de programas. Para m\u00e1s detalles, consulte <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/322823\/\">aqu\u00ed<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/thunk.org\/tytso\/blog\/2009\/03\/12\/delayed-allocation-and-the-zero-length-file-problem\/\">aqu\u00ed<\/a><\/noindex>.<\/p>\n<p>El tercer problema relacionado con <code>fsync()<\/code>, surgi\u00f3 en 2018. Entonces, en el marco del proyecto PostgreSQL, se determin\u00f3 que si la funci\u00f3n <code>fsync()<\/code> se encuentra con un error, marca las p\u00e1ginas \"sucias\" como \"limpias\". Como resultado, las siguientes llamadas <code>fsync()<\/code> No se hacen nada con p\u00e1ginas como estas. Debido a esto, las p\u00e1ginas modificadas se mantienen en memoria y nunca se escriben en el disco. Esto es una verdadera cat\u00e1strofe, ya que la aplicaci\u00f3n considerar\u00e1 que algunos datos se han escrito en el disco, cuando en realidad no ser\u00e1 as\u00ed. Tales fallas <code>fsync()<\/code> son raras, y la aplicaci\u00f3n en tales situaciones casi no puede hacer nada para combatir el problema. En nuestros d\u00edas, cuando eso ocurre, PostgreSQL y otras aplicaciones se cierran inesperadamente. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.usenix.org\/conference\/atc20\/presentation\/rebello\">Aqu\u00ed<\/a><\/noindex>, en el material \"\u00bfPueden las aplicaciones recuperarse de fallos de fsync?\", este problema se investiga en todos los detalles. Actualmente, la mejor soluci\u00f3n a este problema es usar Direct I\/O con la bandera <code>O_SYNC<\/code> o con la bandera <code>O_DSYNC<\/code>. Con este enfoque, el sistema reportar\u00e1 los errores que puedan surgir al ejecutar operaciones espec\u00edficas de escritura de datos, pero este enfoque requiere que la aplicaci\u00f3n gestione los buffers por s\u00ed misma. Lea m\u00e1s sobre esto <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/752063\/\">aqu\u00ed<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Fsync_Errors\">aqu\u00ed<\/a><\/noindex>.<\/p>\n<h2>Apertura de archivos utilizando las banderas O_SYNC y O_DSYNC<\/h2>\n<p>\nVolvemos a discutir los mecanismos de Linux que proporcionan almacenamiento de datos persistente. En particular, se refiere al uso de la bandera <code>O_SYNC<\/code> o de la bandera <code>O_DSYNC<\/code> al abrir archivos utilizando la llamada del sistema <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/open.2.html\">open()<\/a><\/noindex>. Con este enfoque, cada operaci\u00f3n de escritura de datos se realiza como si despu\u00e9s de cada comando <code>write()<\/code> se dieran al sistema, respectivamente, comandos <code>fsync()<\/code> y <code>fdatasync()<\/code>. Hay <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/009695399\/basedefs\/xbd_chap03.html#tag_03_373\">de la especificaci\u00f3n POSIX<\/a><\/noindex> esto se llama \"Finalizaci\u00f3n de Integridad de Archivos de Entrada\/Salida Sincronizados\" y \"Finalizaci\u00f3n de Integridad de Datos\". La principal ventaja de este enfoque es que solo se necesita realizar una llamada al sistema para garantizar la integridad de los datos, en lugar de dos (por ejemplo, <code>write()<\/code> y <code>fdatasync()<\/code>). La principal desventaja de este enfoque es que todas las operaciones de escritura que utilicen el descriptor de archivo correspondiente estar\u00e1n sincronizadas, lo que puede limitar las posibilidades de estructuraci\u00f3n del c\u00f3digo de la aplicaci\u00f3n.<\/p>\n<h2>El uso de Direct I\/O con la bandera O_DIRECT<\/h2>\n<p>\nLlamada del sistema <code>open()<\/code> soporta la bandera <code>O_DIRECT<\/code>, que est\u00e1 dise\u00f1ada para realizar operaciones de entrada\/salida, interactuando directamente con el disco, omitiendo la cach\u00e9 del sistema operativo. Esto, en muchos casos, significa que los comandos de escritura emitidos por el programa se traducir\u00e1n directamente en comandos dirigidos a trabajar con el disco. Pero, en general, este mecanismo no reemplaza las funciones <code>fsync()<\/code> o <code>fdatasync()<\/code>. El hecho es que el propio disco puede <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">retrasar o almacenar en cach\u00e9<\/a><\/noindex> los comandos correspondientes para la escritura de datos. Y, lo que es peor, en algunos casos especiales, las operaciones de entrada y salida realizadas utilizando la bandera <code>O_DIRECT<\/code>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ext4.wiki.kernel.org\/index.php\/Clarifying_Direct_IO%27s_Semantics\">se trasladan<\/a><\/noindex> a operaciones de escritura en b\u00fafer tradicionales. La forma m\u00e1s f\u00e1cil de resolver este problema es abrir archivos tambi\u00e9n con la bandera <code>O_DSYNC<\/code>, lo que significa que cada operaci\u00f3n de escritura ir\u00e1 seguida de una llamada <code>fdatasync()<\/code>.<\/p>\n<p>Resulta que en el sistema de archivos XFS se ha a\u00f1adido recientemente un \"atajo\" para <code>O_DIRECT|O_DSYNC<\/code>-la escritura de datos. Si se vuelve a escribir un bloque utilizando <code>O_DIRECT|O_DSYNC<\/code>, entonces XFS, en lugar de vaciar el cach\u00e9, ejecutar\u00e1 el comando FUA de escritura si el dispositivo lo soporta. Me di cuenta de esto al usar la herramienta <code>blktrace<\/code> en Linux 5.4\/Ubuntu 20.04. Este enfoque deber\u00eda ser m\u00e1s eficiente, ya que al utilizarlo se escribe en el disco una cantidad m\u00ednima de datos y se aplica una sola operaci\u00f3n, no dos (escritura y vaciado del cach\u00e9). Encontr\u00e9 un enlace a <noindex><a rel=\"nofollow\" href=\"https:\/\/patchwork.kernel.org\/patch\/10250257\/\">parche<\/a><\/noindex> un n\u00facleo de 2018 en el que se implement\u00f3 este mecanismo. All\u00ed hay una discusi\u00f3n sobre la aplicaci\u00f3n de esta optimizaci\u00f3n en otros sistemas de archivos, pero, por lo que s\u00e9, XFS es hasta ahora el \u00fanico sistema de archivos que lo soporta.<\/p>\n<h2>La funci\u00f3n sync_file_range()<\/h2>\n<p>\nEn Linux hay una llamada al sistema <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/sync_file_range.2.html\">sync_file_range()<\/a><\/noindex>, que permite vaciar en disco solo una parte del archivo, no todo el archivo. Esta llamada inicia un vaciado as\u00edncrono de datos y no espera a que se complete. Pero en la documentaci\u00f3n de <code>sync_file_range()<\/code> se menciona que este comando es \"muy peligroso\". No se recomienda su uso. Las caracter\u00edsticas y peligros <code>sync_file_range()<\/code> est\u00e1n muy bien descritos en <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2014\/03\/how-syncfilerange-really-works.html\">este<\/a><\/noindex> el material. En particular, parece que esta llamada utiliza RocksDB para gestionar cu\u00e1ndo el n\u00facleo vac\u00eda los datos \"sucios\" en el disco. Pero al mismo tiempo, all\u00ed, para garantizar el almacenamiento persistente de datos, se emplea tambi\u00e9n <code>fdatasync()<\/code>. Hay <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/rocksdb\/search?q=sync_file_range\">el c\u00f3digo<\/a><\/noindex> RocksDB tiene comentarios interesantes sobre este tema. Por ejemplo, parece que la llamada <code>sync_file_range()<\/code> al usar ZFS no provoca el vaciado de datos en el disco. La experiencia me indica que el c\u00f3digo que se utiliza raramente puede contener errores. Por lo tanto, recomendar\u00eda no utilizar esta llamada al sistema sin necesidad extrema.<\/p>\n<h2>Llamadas al sistema que ayudan a garantizar el almacenamiento persistente de datos.<\/h2>\n<p>\nHe llegado a la conclusi\u00f3n de que, para realizar operaciones de entrada\/salida que garanticen un almacenamiento de datos sostenible, se pueden utilizar tres enfoques. Todos ellos requieren invocar la funci\u00f3n <code>fsync()<\/code> para el directorio donde se cre\u00f3 el archivo. Estos son los enfoques:<\/p>\n<ol>\n<li>Invocar la funci\u00f3n <code>fdatasync()<\/code> o <code>fsync()<\/code> despu\u00e9s de la funci\u00f3n <code>write()<\/code> (es mejor usar <code>fdatasync()<\/code>).<\/li>\n<li>Trabajar con el descriptor de archivo abierto con la bandera <code>O_DSYNC<\/code> o <code>O_SYNC<\/code> (es mejor\u2014 con la bandera <code>O_DSYNC<\/code>).<\/li>\n<li>Usar el comando <code>pwritev2()<\/code> con la bandera <code>RWF_DSYNC<\/code> o <code>RWF_SYNC<\/code> (es preferible\u2014 con la bandera <code>RWF_DSYNC<\/code>).<\/li>\n<\/ol>\n<p><\/p>\n<h2>Notas sobre rendimiento<\/h2>\n<p>\nNo he realizado una medici\u00f3n minuciosa del rendimiento de los diversos mecanismos que he investigado. Las diferencias en la velocidad que he notado son bastante peque\u00f1as. Esto significa que podr\u00eda estar equivocado y que, bajo otras condiciones, lo mismo podr\u00eda mostrar resultados diferentes. Primero hablar\u00e9 sobre lo que afecta m\u00e1s al rendimiento y luego sobre lo que influye menos en el rendimiento.<\/p>\n<ol>\n<li>La sobrescritura de datos del archivo es m\u00e1s r\u00e1pida que la anexi\u00f3n de datos al archivo (la ganancia en rendimiento puede ser del 2 al 100%). Anexar datos a un archivo requiere hacer cambios adicionales en los metadatos del archivo, incluso despu\u00e9s de la llamada al sistema <code>fallocate()<\/code>, pero la magnitud de este efecto puede variar. Recomiendo, para asegurar el mejor rendimiento, invocar <code>fallocate()<\/code> para la asignaci\u00f3n previa del espacio necesario. Luego, este espacio debe llenarse expl\u00edcitamente con ceros y se debe invocar <code>fsync()<\/code>. Gracias a esto, los bloques correspondientes en el sistema de archivos ser\u00e1n marcados como \"asignados\", no como \"no asignados\". Esto proporciona una peque\u00f1a (alrededor del 2%) mejora del rendimiento. Adem\u00e1s, en algunos discos, la primera operaci\u00f3n de acceso a un bloque puede realizarse m\u00e1s lentamente que las dem\u00e1s. Esto significa que llenar el espacio con ceros puede conducir a una mejora significativa (alrededor del 100%) en el rendimiento. En particular, esto puede ocurrir con los discos <noindex><a rel=\"nofollow\" href=\"https:\/\/n2ws.com\/blog\/how-to-guides\/pre-warm-ebs-volumes-on-aws\">AWS EBS<\/a><\/noindex> (estos son datos no oficiales, no pude confirmarlos). Lo mismo se aplica a los almacenes <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/compute\/docs\/disks\/benchmarking-pd-performance\">GCP Persistent Disk<\/a><\/noindex> (y esta es ya informaci\u00f3n oficial, corroborada por pruebas). Otros expertos han hecho observaciones similares <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2009\/05\/overwriting-is-much-faster-than_28.html\">, relacionadas con diferentes discos.<\/a><\/noindex>Cuantos menos llamados al sistema, mayor es el rendimiento (la ganancia puede ser de alrededor del 5%). Parece que invocar<\/li>\n<li>o invocar <code>open()<\/code> con la bandera <code>O_DSYNC<\/code> es m\u00e1s r\u00e1pido que la llamada <code>pwritev2()<\/code> con la bandera <code>RWF_SYNC<\/code> m\u00e1s r\u00e1pido de llamar <code>fdatasync()<\/code>Sospecho que esto se debe a que, con este enfoque, lo que importa es que para resolver una misma tarea se requieren menos llamadas del sistema (una llamada en lugar de dos). Pero la diferencia en el rendimiento es muy peque\u00f1a, por lo que puedes no prestarle atenci\u00f3n y usar en tu aplicaci\u00f3n lo que no compliqu\u00e9 su l\u00f3gica.<\/li>\n<\/ol>\n<p>\nSi te interesa el tema del almacenamiento sostenible de datos, aqu\u00ed tienes algunos materiales \u00fatiles:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.scylladb.com\/2017\/10\/05\/io-access-methods-scylla\/\">M\u00e9todos de acceso I\/O<\/a><\/noindex> \u2014 una revisi\u00f3n de los mecanismos b\u00e1sicos de entrada\/salida.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">Asegurando que los datos lleguen al disco<\/a><\/noindex> \u2014 un relato sobre lo que sucede con los datos en su camino desde la aplicaci\u00f3n hasta el disco.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.quora.com\/When-should-you-fsync-the-containing-directory-in-addition-to-the-file-itself\">Cu\u00e1ndo deber\u00edas fsync la carpeta contenedora<\/a><\/noindex> \u2014 una respuesta a la pregunta de cu\u00e1ndo aplicar <code>fsync()<\/code> para carpetas. Si lo resumimos en pocas palabras, se debe hacer al crear un nuevo archivo, y la raz\u00f3n de esta recomendaci\u00f3n es que en Linux puede haber muchos enlaces a un mismo archivo.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/bobsql.com\/sql-server-on-linux-forced-unit-access-fua-internals\/\">SQL Server en Linux: Internos de FUA<\/a><\/noindex> \u2014 aqu\u00ed se describe c\u00f3mo se implementa el almacenamiento sostenible de datos en SQL Server en la plataforma Linux. Se presentan algunas comparaciones interesantes entre las llamadas del sistema de Windows y Linux. Estoy casi seguro de que gracias a este material supe sobre la optimizaci\u00f3n FUA en XFS.<\/li>\n<\/ul>\n<p>\n\u00bfHas perdido datos que pensabas que estaban guardados de manera segura en el disco?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/ruvds.com\/ru-rub?utm_source=habr&amp;utm_medium=article&amp;utm_campaign=perevod&amp;utm_content=ustojchivoe_xranenie_dannyx_i_fajlovye_api_linux#order\"><img decoding=\"async\" alt=\"Almacenamiento de datos sostenible y API de archivos en Linux\" src=\"\/wp-content\/uploads\/2020\/10\/8bea3fc2b65a5a683655d9c15e153c93.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/ruvds.com\/ru-rub\/news\/read\/123?utm_source=habr&amp;utm_medium=article&amp;utm_campaign=perevod&amp;utm_content=ustojchivoe_xranenie_dannyx_i_fajlovye_api_linux\"><img decoding=\"async\" alt=\"Almacenamiento de datos sostenible y API de archivos en Linux\" src=\"\/wp-content\/uploads\/2020\/10\/d9fd0b1c09eb6e40944aee2d13ee4088.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/524172\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042f, \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0431\u044f, \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438. \u042f \u043d\u0430\u0447\u0430\u043b \u0441 \u0447\u0442\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 NVMe \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a\u0438\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438, \u043a\u0430\u0441\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 (\u0442\u043e \u0435\u0441\u0442\u044c \u2014 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b), \u0434\u0430\u044e\u0442 \u043d\u0430\u043c NMVe-\u0434\u0438\u0441\u043a\u0438. \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":98091,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-98090","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042f, \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0431\u044f, \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0423\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0435 API Linux | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042f, \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0431\u044f, \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-10-24T00:42:38+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-11-17T22:58:48+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 Almacenamiento sostenible de datos y API de archivos en Linux | ProHoster","description":"Yo, explorando la resistencia del almacenamiento de datos en sistemas en la nube, decid\u00ed ponerme a prueba, asegurarme de que entend\u00eda las cosas b\u00e1sicas.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0423\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0435 API Linux | ProHoster","og:description":"\u042f, \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0431\u044f, \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-10-24T00:42:38+00:00","article:modified_time":"2020-11-17T22:58:48+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"98090","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:05:49","updated":"2026-08-11 12:50:05","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/98090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=98090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/98090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/98091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=98090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=98090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=98090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}