{"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\/it\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","title":{"rendered":"Archiviazione dati sostenibile e API file Linux","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Mentre esploravo la resilienza dello storage nei sistemi cloud, ho deciso di mettermi alla prova, per assicurarmi di comprendere le basi. Ho <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">iniziato leggendo la specifica NVMe<\/a><\/noindex> per capire quali garanzie riguardanti la resilienza dei dati (cio\u00e8 le garanzie che i dati saranno disponibili dopo un guasto del sistema) ci offrono i dischi NVMe. Ho tratto le seguenti conclusioni principali: i dati devono essere considerati danneggiati dal momento in cui viene dato l'ordine di scrittura e fino a quando la scrittura non \u00e8 completata sul supporto. Tuttavia, nella maggior parte dei programmi di scrittura dei dati, vengono spesso utilizzate tranquillamente chiamate di sistema.<\/p>\n<p>In questo materiale, esaminer\u00f2 i meccanismi di resilienza dei dati forniti dalle API di file di Linux. Sembra che qui tutto dovrebbe essere semplice: il programma invoca il comando <code>write()<\/code>, e dopo che il comando ha terminato la sua esecuzione, i dati dovrebbero essere salvati in modo affidabile sul disco. Ma <code>write()<\/code> esso copia solo i dati dell'applicazione nella cache del kernel, che si trova nella memoria principale. Per costringere il sistema a scrivere i dati sul disco, \u00e8 necessario utilizzare alcuni meccanismi aggiuntivi.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/524172\/\"><img decoding=\"async\" alt=\"Archiviazione dati sostenibile e API file Linux\" src=\"\/wp-content\/uploads\/2020\/10\/b974dcb9fc546cae03ade4f3d8f5dc25.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>In generale, questo materiale rappresenta un insieme di appunti riguardo a ci\u00f2 che ho appreso sull'argomento che mi interessa. Se si desidera riassumere brevemente il punto pi\u00f9 importante, si pu\u00f2 affermare che per garantire la resilienza dei dati \u00e8 necessario utilizzare il comando <code>fdatasync()<\/code> o aprire i file con il flag <code>O_DSYNC<\/code>. Se sei interessato a scoprire nei dettagli ci\u00f2 che accade ai dati nel percorso dal codice sorgente al disco, dai un'occhiata a <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">questa<\/a><\/noindex> articolo.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Caratteristiche dell'uso della funzione write()<\/h2>\n<p>\nChiamata di sistema <code>write()<\/code> definito nello standard <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/POSIX\">IEEE POSIX<\/a><\/noindex> come un tentativo di scrivere dati in un descrittore di file. Dopo il completamento con successo, <code>write()<\/code> le operazioni di lettura dei dati devono restituire esattamente quei byte che erano stati precedentemente scritti, anche se i dati vengono accessibili da altri processi o thread (<noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/write.html#tag_16_685_08\">ecco<\/a><\/noindex> la sezione corrispondente dello standard POSIX). <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/V2_chap02.html#tag_15_09_07\">Qui<\/a><\/noindex>, nella sezione dedicata all'interazione dei thread con le normali operazioni sui file, c'\u00e8 una nota che afferma che se entrambi i thread chiamano queste funzioni, ogni chiamata deve vedere o tutte le conseguenze designate derivanti dall'esecuzione di un'altra chiamata, oppure non deve vedere alcuna conseguenza. Questo porta alla conclusione che tutte le operazioni di input\/output sui file devono mantenere il blocco della risorsa su cui operano.<\/p>\n<p>Significa questo che l'operazione <code>write()<\/code> \u00e8 atomica? Dal punto di vista tecnico \u2014 s\u00ec. Le operazioni di lettura dei dati devono restituire tutto o nulla di ci\u00f2 che \u00e8 stato scritto tramite <code>write()<\/code>. Ma l'operazione <code>write()<\/code>, secondo lo standard, non deve necessariamente completarsi scrivendo tutto ci\u00f2 che le \u00e8 stato proposto di scrivere. \u00c8 permesso scrivere solo una parte dei dati. Ad esempio, possiamo avere due thread, ognuno dei quali aggiunge 1024 byte a un file identificato dallo stesso descrittore di file. Dal punto di vista dello standard, \u00e8 accettabile che ogni operazione di scrittura possa aggiungere solo un byte al file. Queste operazioni rimarranno atomiche, ma una volta completate, i dati scritti nel file risulteranno mescolati. <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/a\/42442926\/413438\">Ecco<\/a><\/noindex> c'\u00e8 una discussione molto interessante su questo argomento su Stack Overflow.<\/p>\n<h2>Le funzioni fsync() e fdatasync()<\/h2>\n<p>\nIl modo pi\u00f9 semplice per scrivere i dati su disco \u00e8 invocare la funzione <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fsync.2.html\">fsync()<\/a><\/noindex>. Questa funzione richiede al sistema operativo di trasferire tutti i blocchi modificati dalla cache al disco. Questo include anche tutti i metadati del file (tempo di accesso, tempo di modifica del file e cos\u00ec via). Penso che la necessit\u00e0 di questi metadati si verifichi raramente, quindi se sai che non ti sono importanti, puoi utilizzare la funzione <code>fdatasync()<\/code>. In <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fdatasync.2.html\">informativa<\/a><\/noindex> da <code>fdatasync()<\/code> afferma che nel corso di questa funzione viene eseguito il salvataggio su disco di un volume di metadati che \u00e8 \u201cnecessario per l'esecuzione corretta delle operazioni di lettura successiva sui dati\u201d. E questo \u00e8 esattamente ci\u00f2 che preoccupa la maggior parte delle applicazioni.<\/p>\n<p>Uno dei problemi che possono sorgere qui \u00e8 che questi meccanismi non garantiscono che il file possa essere rilevato dopo un possibile guasto. In particolare, quando si crea un nuovo file, \u00e8 necessario invocare <code>fsync()<\/code> per la directory che lo contiene. Altrimenti, dopo un guasto, potrebbe risultare che questo file non esiste. La ragione di ci\u00f2 \u00e8 che in UNIX, a causa dell'uso di collegamenti rigidi, un file pu\u00f2 esistere in pi\u00f9 directory. Quindi, quando viene chiamato <code>fsync()<\/code> non c'\u00e8 modo per il file di sapere quali dati di quale directory devono essere scritti su disco (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.quora.com\/When-should-you-fsync-the-containing-directory-in-addition-to-the-file-itself\">qui<\/a><\/noindex> si pu\u00f2 leggere di pi\u00f9 al riguardo). Sembra che il file system ext4 sia in grado <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/799807\/\">installati automaticamente<\/a><\/noindex> di applicare <code>fsync()<\/code> alle directory che contengono i file corrispondenti, ma nel caso di altri file system, potrebbe non essere cos\u00ec.<\/p>\n<p>Questo meccanismo pu\u00f2 essere implementato in modo diverso nei vari file system. Ho usato <noindex><a rel=\"nofollow\" href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/axboe\/blktrace.git\/tree\/README\">blktrace<\/a><\/noindex> per scoprire quali operazioni su disco vengono utilizzate nei file system ext4 e XFS. Entrambi emettono normali comandi di scrittura su disco sia per i contenuti dei file che per il journaling del file system, svuotano la cache e terminano l'operazione eseguendo una scrittura FUA (Force Unit Access, scrittura dei dati direttamente su disco, bypassando la cache) nel journal. \u00c8 probabile che procedano in questo modo per confermare l'operazione eseguita. Su dischi che non supportano FUA, ci\u00f2 provoca due svuotamenti della cache. I miei esperimenti hanno dimostrato che <code>fdatasync()<\/code> \u00e8 un po' pi\u00f9 veloce <code>fsync()<\/code>. L'utilit\u00e0 <code>blktrace<\/code> indica che <code>fdatasync()<\/code> scrive normalmente meno dati su disco (in ext4 <code>fsync()<\/code> scrive 20 KiB, mentre <code>fdatasync()<\/code> ne scrive 16 KiB). Inoltre, ho scoperto che XFS \u00e8 leggermente pi\u00f9 veloce di ext4. E qui sono riuscito a scoprire che <code>blktrace<\/code> svuota su disco meno dati (4 KiB in XFS). <code>fdatasync()<\/code> Situazioni ambigue che sorgono con l'uso di fsync()<\/p>\n<h2>Posso ricordare tre situazioni ambigue riguardo<\/h2>\n<p>\n, con cui mi sono imbattuto nella pratica. <code>fsync()<\/code>Il primo di questi casi \u00e8 avvenuto nel 2008. In quel momento, l'interfaccia di Firefox 3 'si bloccava' quando veniva scritta su disco una grande quantit\u00e0 di file. Il problema era che nell'implementazione dell'interfaccia per memorizzare informazioni sul suo stato veniva utilizzato un database SQLite. Dopo ogni modifica avvenuta nell'interfaccia, veniva chiamata la funzione<\/p>\n<p>, il che garantiva buone garanzie di persistenza dei dati. Nella file system utilizzata all'epoca, ext3, la funzione <code>fsync()<\/code>, che forniva buone garanzie di archiviazione stabile dei dati. Nella filesystem ext3 utilizzata allora, la funzione <code>fsync()<\/code> reindirizzava su disco tutte le pagine \"sporche\" nel sistema, e non solo quelle correlate al file pertinente. Ci\u00f2 significava che un clic su un pulsante in Firefox poteva avviare la scrittura di megabyte di dati su disco rigido, cosa che poteva richiedere molti secondi. Ho compreso la soluzione al problema da <noindex><a rel=\"nofollow\" href=\"http:\/\/shaver.off.net\/diary\/2008\/05\/25\/fsyncers-and-curveballs\/\">di questo<\/a><\/noindex> materiale che era quella di spostare il lavoro con il database in attivit\u00e0 di fondo asincrone. Ci\u00f2 implica che in precedenza in Firefox erano stati implementati requisiti di robustezza del salvataggio dei dati molto pi\u00f9 severi di quanto fosse realmente necessario, e le peculiarit\u00e0 del file system ext3 hanno solo aggravato questo problema.<\/p>\n<p>Il secondo inconveniente si \u00e8 verificato nel 2009. In quell'anno, dopo un guasto del sistema, gli utenti del nuovo file system ext4 si sono trovati di fronte al fatto che molti file di recente creazione avevano una lunghezza zero, mentre con il file system pi\u00f9 vecchio ext3 non si \u00e8 verificato nulla di simile. Nel paragrafo precedente accennavo al fatto che l'ext3 scriveva troppi dati su disco, il che rallentava notevolmente le operazioni <code>fsync()<\/code>. Per migliorare la situazione, in ext4 vengono scritte su disco solo le \"pagine sporche\" che sono correlate a un file specifico. I dati degli altri file rimangono in memoria per un tempo molto pi\u00f9 lungo rispetto a quanto avveniva con l'uso dell'ext3. Questo \u00e8 stato fatto per migliorare le prestazioni (per impostazione predefinita, i dati rimangono in questo stato per 30 secondi, e questo pu\u00f2 essere configurato tramite <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\">qui<\/a><\/noindex> , si possono trovare ulteriori materiali a riguardo). Ci\u00f2 significa che una grande quantit\u00e0 di dati pu\u00f2 essere permanentemente persa dopo un guasto. La soluzione a questo problema consiste nell'utilizzo di <code>fsync()<\/code> applicazioni che necessitano di garantire una conservazione affidabile dei dati e proteggere al massimo dalle conseguenze dei guasti. La funzione <code>fsync()<\/code> opera con l'ext4 in modo significativamente pi\u00f9 efficace rispetto all'ext3. Il rovescio della medaglia di questo approccio \u00e8 che la sua applicazione, come in passato, rallenta l'esecuzione di alcune operazioni, come l'installazione di programmi. Maggiori dettagli su questo si possono trovare <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/322823\/\">qui<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/thunk.org\/tytso\/blog\/2009\/03\/12\/delayed-allocation-and-the-zero-length-file-problem\/\">qui<\/a><\/noindex>.<\/p>\n<p>Il terzo problema riguardante <code>fsync()<\/code>, \u00e8 emerso nel 2018. In quell'anno, nell'ambito del progetto PostgreSQL, \u00e8 stato scoperto che se la funzione <code>fsync()<\/code> incontra un errore, contrassegna le \"pagine sporche\" come \"pulite\". Di conseguenza, le chiamate successive <code>fsync()<\/code> non si fa niente con queste pagine. A causa di ci\u00f2, le pagine modificate rimangono in memoria e non vengono mai scritte su disco. Questa \u00e8 una vera catastrofe, poich\u00e9 l'applicazione penser\u00e0 che alcuni dati siano stati scritti su disco, ma in realt\u00e0 cos\u00ec non \u00e8. Questi malfunzionamenti <code>fsync()<\/code> si verificano raramente, l'applicazione in queste situazioni pu\u00f2 fare quasi nulla per affrontare il problema. Al giorno d'oggi, quando ci\u00f2 accade, PostgreSQL e altre applicazioni terminano improvvisamente. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.usenix.org\/conference\/atc20\/presentation\/rebello\">Qui<\/a><\/noindex>, nel materiale \"Can Applications Recover from fsync Failures?\", questo problema viene studiato in tutti i dettagli. Attualmente, la miglior soluzione per questo problema \u00e8 utilizzare Direct I\/O con il flag <code>O_SYNC<\/code> o con il flag <code>O_DSYNC<\/code>. Con questo approccio, il sistema segnaler\u00e0 gli errori che possono verificarsi durante l'esecuzione di operazioni specifiche di scrittura dei dati, ma questo approccio richiede che l'applicazione gestisca i buffer autonomamente. Maggiori dettagli su questo possono essere letti <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/752063\/\">qui<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Fsync_Errors\">qui<\/a><\/noindex>.<\/p>\n<h2>Apertura di file con i flag O_SYNC e O_DSYNC<\/h2>\n<p>\nTorniamo a discutere dei meccanismi di Linux che garantiscono l'integrit\u00e0 dei dati. In particolare, si tratta dell'uso del flag <code>O_SYNC<\/code> o del flag <code>O_DSYNC<\/code> quando si aprono file usando la chiamata di sistema <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/open.2.html\">open()<\/a><\/noindex>. Con questo approccio, ogni operazione di scrittura di dati viene eseguita come se dopo ogni comando <code>write()<\/code> al sistema venissero date, rispettivamente, le istruzioni <code>fsync()<\/code> e <code>fdatasync()<\/code>. In <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/009695399\/basedefs\/xbd_chap03.html#tag_03_373\">specifiche POSIX<\/a><\/noindex> questo \u00e8 chiamato \"Synchronized I\/O File Integrity Completion\" e \"Data Integrity Completion\". Il principale vantaggio di questo approccio \u00e8 che per garantire l'integrit\u00e0 dei dati \u00e8 necessario eseguire solo una chiamata di sistema, e non due (ad esempio - <code>write()<\/code> e <code>fdatasync()<\/code>). Lo svantaggio principale di questo approccio \u00e8 che tutte le operazioni di scrittura che utilizzano il relativo descrittore di file saranno sincronizzate, il che pu\u00f2 limitare le possibilit\u00e0 di strutturare il codice dell'applicazione.<\/p>\n<h2>L'uso di Direct I\/O con il flag O_DIRECT<\/h2>\n<p>\nChiamata di sistema <code>open()<\/code> supporta il flag <code>O_DIRECT<\/code>, che \u00e8 progettato per eseguire operazioni di input\/output bypassando la cache del sistema operativo, interagendo direttamente con il disco. Questo, in molti casi, significa che i comandi di scrittura emessi dal programma verranno direttamente tradotti in comandi destinati a lavorare con il disco. Ma, in generale, questo meccanismo non sostituisce le funzioni <code>fsync()<\/code> o <code>fdatasync()<\/code>. Il fatto \u00e8 che il disco stesso pu\u00f2 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">rinviare o memorizzare in cache<\/a><\/noindex> i comandi corretti per la scrittura dei dati. E, peggio ancora, in alcuni casi particolari, le operazioni di input\/output eseguite utilizzando il flag <code>O_DIRECT<\/code>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ext4.wiki.kernel.org\/index.php\/Clarifying_Direct_IO%27s_Semantics\">vengono tradotte<\/a><\/noindex> in operazioni di buffering tradizionali. Il modo pi\u00f9 semplice per risolvere questo problema \u00e8 utilizzare anche il flag per aprire i file <code>O_DSYNC<\/code>, il che significher\u00e0 che ad ogni operazione di scrittura seguir\u00e0 una chiamata <code>fdatasync()<\/code>.<\/p>\n<p>\u00c8 emerso che nel file system XFS \u00e8 stato recentemente aggiunto un 'percorso veloce' per <code>O_DIRECT|O_DSYNC<\/code>-la scrittura dei dati. Se si riporta un blocco utilizzando <code>O_DIRECT|O_DSYNC<\/code>, XFS, invece di svuotare la cache, eseguir\u00e0 il comando di scrittura FUA se l'hardware lo supporta. Ne ho avuto conferma utilizzando l'utilit\u00e0 <code>blktrace<\/code> nel sistema Linux 5.4\/Ubuntu 20.04. Questo approccio dovrebbe essere pi\u00f9 efficace, poich\u00e9 riduce al minimo la quantit\u00e0 di dati scritti su disco e utilizza un'unica operazione anzich\u00e9 due (scrittura e svuotamento della cache). Ho trovato un collegamento al <noindex><a rel=\"nofollow\" href=\"https:\/\/patchwork.kernel.org\/patch\/10250257\/\">patch<\/a><\/noindex> kernel del 2018, in cui \u00e8 stato implementato questo meccanismo. L\u00ec c'\u00e8 una discussione relativa all'applicazione di questa ottimizzazione anche in altri file system, ma, per quanto ne so, XFS \u00e8 l'unico file system che attualmente lo supporta.<\/p>\n<h2>La funzione sync_file_range()<\/h2>\n<p>\nIn Linux esiste una chiamata di sistema <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/sync_file_range.2.html\">sync_file_range()<\/a><\/noindex>, che consente di svuotare su disco solo una parte di un file, non l'intero file. Questa chiamata avvia uno svuotamento asincrono dei dati e non ne attende il completamento. Ma nella documentazione <code>sync_file_range()<\/code> si afferma che questo comando \u00e8 'molto pericoloso'. Non \u00e8 consigliabile usarlo. Le caratteristiche e i pericoli <code>sync_file_range()<\/code> sono descritti molto bene nel <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2014\/03\/how-syncfilerange-really-works.html\">seguente<\/a><\/noindex> materiale. In particolare, sembra che questa chiamata utilizzi RocksDB per gestire quando il kernel svuota i dati 'sporchi' su disco. Ma al contempo, per garantire una memorizzazione persistente dei dati, utilizza anche <code>fdatasync()<\/code>. In <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/rocksdb\/search?q=sync_file_range\">codice<\/a><\/noindex> RocksDB ci sono commenti interessanti su questo argomento. Ad esempio, sembra che la chiamata <code>sync_file_range()<\/code> quando si utilizza ZFS non comporti lo svuotamento dei dati su disco. L'esperienza mi dice che il codice che viene usato raramente potrebbe contenere errori. Pertanto, consiglio di non utilizzare questa chiamata di sistema senza un'urgente necessit\u00e0.<\/p>\n<h2>Le chiamate di sistema che aiutano a garantire una conservazione persistente dei dati<\/h2>\n<p>\nSono giunto alla conclusione che per effettuare operazioni di input\/output che garantiscano una conservazione persistente dei dati, si possono adottare tre approcci. Tutti richiedono la chiamata della funzione <code>fsync()<\/code> per la directory in cui \u00e8 stato creato il file. Ecco questi approcci:<\/p>\n<ol>\n<li>Chiamata della funzione <code>fdatasync()<\/code> o <code>fsync()<\/code> dopo la funzione <code>write()<\/code> (\u00e8 meglio utilizzare <code>fdatasync()<\/code>).<\/li>\n<li>Lavorare con il descrittore di file, aperto con il flag <code>O_DSYNC<\/code> o <code>O_SYNC<\/code> (meglio \u2014 con il flag <code>O_DSYNC<\/code>).<\/li>\n<li>Utilizzo del comando <code>pwritev2()<\/code> con il flag <code>RWF_DSYNC<\/code> o <code>RWF_SYNC<\/code> (preferibilmente \u2014 con il flag <code>RWF_DSYNC<\/code>).<\/li>\n<\/ol>\n<p><\/p>\n<h2>Note sulle prestazioni<\/h2>\n<p>\nNon ho effettuato misurazioni accurate delle prestazioni dei vari meccanismi che ho esaminato. Le differenze di velocit\u00e0 che ho notato sono piuttosto minime. Questo significa che potrei sbagliarmi, e che in altre condizioni potrebbe mostrare risultati diversi. Inizier\u00f2 a parlare di ci\u00f2 che influisce maggiormente sulle prestazioni, e poi di ci\u00f2 che influisce meno.<\/p>\n<ol>\n<li>La riscrittura dei dati di un file \u00e8 pi\u00f9 veloce dell'aggiunta di dati a un file (il guadagno in prestazioni pu\u00f2 variare dal 2% al 100%). L'aggiunta di dati a un file richiede modifiche aggiuntive ai metadati del file, anche dopo la chiamata di sistema <code>fallocate()<\/code>, ma l'entit\u00e0 di questo effetto pu\u00f2 variare. Raccomando, per garantire le migliori prestazioni, di chiamare <code>fallocate()<\/code> per l'allocazione anticipata dello spazio necessario. Dopo, questo spazio deve essere esplicitamente riempito di zeri e chiamare <code>fsync()<\/code>. Questo consente ai relativi blocchi nel file system di essere contrassegnati come \"allocati\" e non come \"non allocati\". Questo apporta un piccolo (circa il 2%) miglioramento delle prestazioni. Inoltre, alcuni dischi possono avere la prima operazione di accesso a un blocco che potrebbe richiedere pi\u00f9 tempo rispetto ad altri. Ci\u00f2 significa che riempire lo spazio di zeri pu\u00f2 portare a un miglioramento significativo (circa il 100%) delle prestazioni. In particolare, ci\u00f2 pu\u00f2 avvenire con i dischi <noindex><a rel=\"nofollow\" href=\"https:\/\/n2ws.com\/blog\/how-to-guides\/pre-warm-ebs-volumes-on-aws\">AWS EBS<\/a><\/noindex> (questi sono dati non ufficiali, non sono riuscito a confermarli). Lo stesso vale per gli storage <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/compute\/docs\/disks\/benchmarking-pd-performance\">GCP Persistent Disk<\/a><\/noindex> (questo \u00e8 invece un dato ufficiale, confermato dai test). Altri specialisti hanno fatto osservazioni simili <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2009\/05\/overwriting-is-much-faster-than_28.html\">, relative a diversi dischi.<\/a><\/noindex>Meno chiamate di sistema ci sono, maggiore \u00e8 la prestazione (il guadagno pu\u00f2 essere circa il 5%). Sembra che la chiamata<\/li>\n<li>o la chiamata <code>open()<\/code> con il flag <code>O_DSYNC<\/code> sia pi\u00f9 veloce della chiamata <code>pwritev2()<\/code> con il flag <code>RWF_SYNC<\/code> richiama pi\u00f9 rapidamente <code>fdatasync()<\/code>Sospetto che il motivo risieda nel fatto che, con questo approccio, il numero di chiamate di sistema necessarie per risolvere lo stesso compito \u00e8 ridotto (una chiamata invece di due). Tuttavia, la differenza nelle prestazioni \u00e8 molto piccola, quindi potete ignorarla e utilizzare nell'applicazione ci\u00f2 che non porter\u00e0 a complicare la sua logica.<\/li>\n<\/ol>\n<p>\nSe siete interessati al tema dell'archiviazione dati sicura, ecco alcuni materiali utili:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.scylladb.com\/2017\/10\/05\/io-access-methods-scylla\/\">Metodi di accesso I\/O<\/a><\/noindex> \u2014 una panoramica dei principali meccanismi di input\/output.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">Assicurare che i dati raggiungano il disco<\/a><\/noindex> \u2014 una spiegazione di cosa succede ai dati mentre viaggiano dall'applicazione al 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\">Quando dovreste fsyncare la directory contenente<\/a><\/noindex> \u2014 una risposta su quando applicare <code>fsync()<\/code> per le directory. In breve, \u00e8 consigliabile farlo quando si crea un nuovo file, e il motivo di questo consiglio \u00e8 che in Linux possono esserci molte link a uno stesso file.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/bobsql.com\/sql-server-on-linux-forced-unit-access-fua-internals\/\">SQL Server su Linux: Interni di FUA<\/a><\/noindex> \u2014 qui viene descritto come l'archiviazione dati sicura venga implementata in SQL Server sulla piattaforma Linux. Ci sono anche alcune interessanti comparazioni tra le chiamate di sistema di Windows e Linux. Sono quasi certo di aver appreso dell'ottimizzazione FUA di XFS proprio grazie a questo materiale.<\/li>\n<\/ul>\n<p>\nAvete mai perso dati che pensavate fossero conservati in modo sicuro sul 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=\"Archiviazione dati sostenibile e API file 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=\"Archiviazione dati sostenibile e API file Linux\" src=\"\/wp-content\/uploads\/2020\/10\/d9fd0b1c09eb6e40944aee2d13ee4088.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Fonte: <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.1.1 - 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\/it\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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\udd47Archiviazione dati sicura e API di file Linux | ProHoster","description":"Mentre esploravo la resilienza dell'archiviazione dati nei sistemi cloud, ho deciso di mettermi alla prova, assicurandomi di comprendere le basi.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/98090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=98090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/98090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/98091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=98090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=98090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=98090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}