{"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\/hr\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","title":{"rendered":"Odr\u017eivo pohranjivanje podataka i Linux API-ji za datoteke","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Istra\u017euju\u0107i odr\u017eivost pohrane podataka u oblaku, odlu\u010dio sam provjeriti svoje znanje i uvjeriti se da razumijem osnovne stvari. Ja <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">po\u010deo sam s \u010ditanjem specifikacije NVMe<\/a><\/noindex> kako bih razumio koje nam garancije vezane za odr\u017eivu pohranu podataka (tj. garancije da \u0107e podaci biti dostupni nakon sustavnog kvara) pru\u017eaju NMVe diskovi. Moji glavni zaklju\u010dci su sljede\u0107i: podaci se moraju smatrati o\u0161te\u0107enima od trenutka kada se izdaje naredba za zapis podataka, do trenutka kada zavr\u0161i zapis na medij. Me\u0111utim, u ve\u0107ini programa za zapis podataka, sustavni pozivi se koriste bez problema.<\/p>\n<p>U ovom materijalu ispitat \u0107u mehanizme odr\u017eive pohrane podataka koje pru\u017eaju Linuxove datote\u010dne API-je. \u010cini se da bi to ovdje trebalo biti jednostavno: program izvr\u0161ava naredbu <code>write()<\/code>, a nakon zavr\u0161etka rada te naredbe, podaci \u0107e biti pouzdano pohranjeni na disku. No <code>write()<\/code> samo kopira podatke aplikacije u ke\u0161 jezgre smje\u0161ten u radnoj memoriji. Da bi se prisilila sustav na zapis podataka na disk, potrebno je koristiti neke dodatne mehanizme.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/524172\/\"><img decoding=\"async\" alt=\"Odr\u017eivo pohranjivanje podataka i Linux API-ji za datoteke\" src=\"\/wp-content\/uploads\/2020\/10\/b974dcb9fc546cae03ade4f3d8f5dc25.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>U cjelini, ovaj materijal predstavlja skup bilje\u0161ki o tome \u0161to sam saznao o temi koja me zanima. Ako bih vrlo kratko rekao najva\u017enije, to bi bilo da za organizaciju odr\u017eive pohrane podataka treba koristiti naredbu <code>fdatasync()<\/code> ili otvoriti datoteke s oznakom <code>O_DSYNC<\/code>. Ako vas zanima \u0161to se doga\u0111a s podacima na putu od programskog koda do diska, pogledajte <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">ovu<\/a><\/noindex> \u010dlanak.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Osobitosti kori\u0161tenja funkcije write()<\/h2>\n<p>\nSistem poziv <code>write()<\/code> definiran je u standardu <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/POSIX\">IEEE POSIX<\/a><\/noindex> kao poku\u0161aj zapisivanja podataka u datote\u010dni deskriptor. Nakon uspje\u0161nog zavr\u0161etka <code>write()<\/code> operacije \u010ditanja podaci moraju vra\u0107ati upravo one bajtove koji su prethodno zapisani, \u010dine\u0107i to \u010dak i kada se podacima pristupa iz drugih procesa ili niti (<noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/write.html#tag_16_685_08\">evo<\/a><\/noindex> odgovaraju\u0107i dio standarda POSIX). <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/functions\/V2_chap02.html#tag_15_09_07\">Ovdje<\/a><\/noindex>, u odjeljku posve\u0107enom interakciji tokova s obi\u010dnim datote\u010dnim operacijama, postoji napomena koja ka\u017ee da ako svaki od dva toka poziva te funkcije, svaki poziv treba vidjeti ili sve ozna\u010dene posljedice koje proizlaze iz izvr\u0161enja drugog poziva, ili ne vidjeti nikakve posljedice. To omogu\u0107uje zaklju\u010dak da sve datote\u010dne operacije ulaza\/izlaza moraju zadr\u017eati zaklju\u010davanje resursa s kojim rade.<\/p>\n<p>Zna\u010di li to da je operacija <code>write()<\/code> atomarna? Tehni\u010dki gledano \u2014 da. Operacije \u010ditanja podataka trebaju vra\u0107ati ili sve, ili ni\u0161ta od onoga \u0161to je zapisano pomo\u0107u <code>write()<\/code>. No, operacija <code>write()<\/code>, prema standardu, ne mora nu\u017eno zavr\u0161iti zapisivanjem svega \u0161to je bila odobrena za zapisivanje. Dozvoljeno joj je zapisati samo dio podataka. Na primjer, mo\u017eemo imati dva toka, svaki od kojih pridru\u017euje 1024 bajta datoteci koja se opisuje istim deskriptorom datoteke. Iz perspektive standarda, rezultat u kojem svaka od operacija zapisivanja mo\u017ee pridru\u017eiti samo jedan bajt datoteci bit \u0107e prihvatljiv. Ove operacije ostat \u0107e atomske, ali nakon \u0161to zavr\u0161e, podaci koje su zapisali u datoteku bit \u0107e pomije\u0161ani. <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/a\/42442926\/413438\">Evo<\/a><\/noindex> vrlo zanimljiva rasprava na ovu temu na Stack Overflow-u.<\/p>\n<h2>Funkcije fsync() i fdatasync()<\/h2>\n<p>\nNajjednostavniji na\u010din za isklju\u010divanje podataka na disk je pozivanje funkcije <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fsync.2.html\">fsync()<\/a><\/noindex>. Ova funkcija tra\u017ei od operativnog sustava da prenese sve modificirane blokove iz predmemorije na disk. To uklju\u010duje i sve metapodatke datoteke (vrijeme pristupa, vrijeme modifikacije datoteke itd.). Smatram da je potreba za tim metapodacima rijetka, stoga, ako znate da vam nisu va\u017eni, mo\u017eete koristiti funkciju <code>fdatasync()<\/code>. U <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fdatasync.2.html\">pomo\u0107<\/a><\/noindex> o <code>fdatasync()<\/code> navodi da tijekom rada ove funkcije dolazi do spremanja na disk tog volumena metapodataka koji je \u201eneophodan za pravilno izvr\u0161avanje sljede\u0107ih operacija \u010ditanja podataka\u201d. A to je ono \u0161to brine ve\u0107inu aplikacija.<\/p>\n<p>Jedan od problema koji ovdje mo\u017ee nastati jest to \u0161to ti mehanizmi ne jam\u010de da \u0107e datoteka biti otkrivena nakon mogu\u0107eg kvara. Konkretno, kada se stvara nova datoteka, potrebno je pozvati <code>fsync()<\/code> za direktorij, koji ga sadr\u017ei. Ina\u010de, nakon kvara mo\u017ee se dogoditi da ovaj datoteka ne postoji. Razlog za to je \u0161to u UNIX-u, zbog kori\u0161tenja tvrdih veza, datoteka mo\u017ee postojati u vi\u0161e direktorija. Stoga prilikom pozivanja <code>fsync()<\/code> za datoteku nema na\u010dina da sazna koja to\u010dno direktorija tako\u0111er treba zapisati na disk (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.quora.com\/When-should-you-fsync-the-containing-directory-in-addition-to-the-file-itself\">ovdje<\/a><\/noindex> o tome se mo\u017ee pro\u010ditati detaljnije). \u010cini se da datote\u010dni sustav ext4 mo\u017ee <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/799807\/\">automatski<\/a><\/noindex> se primjenjivati <code>fsync()<\/code> do direktorija koji sadr\u017ee odgovaraju\u0107e datoteke, ali u slu\u010daju drugih datote\u010dnih sustava to mo\u017eda nije tako.<\/p>\n<p>Omekanik mo\u017ee biti razli\u010dito implementiran u razli\u010ditim datote\u010dnim sustavima. Koristio sam <noindex><a rel=\"nofollow\" href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/axboe\/blktrace.git\/tree\/README\">blktrace<\/a><\/noindex> da saznam koje diskovne operacije se koriste u datote\u010dnim sustavima ext4 i XFS. I jedan i drugi daju uobi\u010dajene naredbe za zapis na disk i za sadr\u017eaj datoteka, i za dnevnik datote\u010dnog sustava, ispu\u0161taju ke\u0161 i zavr\u0161avaju rad, izvr\u0161avaju\u0107i FUA-zapis (Force Unit Access, zapis podataka izravno na disk, mimo ke\u0161a) u dnevnik. Vjerojatno to \u010dine kako bi potvrdili \u010dinjenicu da se operacija dogodila. Na diskovima koji ne podr\u017eavaju FUA, to uzrokuje dva ispisa ke\u0161a. Moji eksperimenti su pokazali da <code>fdatasync()<\/code> malo br\u017ee <code>fsync()<\/code>. Alat <code>blktrace<\/code> ukazuje na to da <code>fdatasync()<\/code> obi\u010dno pi\u0161e manje podataka na disk (u ext4 <code>fsync()<\/code> zapisuje 20 KiB, a <code>fdatasync()<\/code> \u2014 16 KiB). Osim toga, otkrio sam da je XFS malo br\u017ei od ext4. A ovdje je uz pomo\u0107 <code>blktrace<\/code> uspjelo saznati da <code>fdatasync()<\/code> ispisuje manje podataka na disk (4 KiB u XFS).<\/p>\n<h2>Nejasne situacije koje nastaju prilikom kori\u0161tenja fsync()<\/h2>\n<p>\nMogu se sjetiti tri nejasne situacije koje se odnose <code>fsync()<\/code>, s kojima sam se susreo u praksi.<\/p>\n<p>Prvi takav slu\u010daj dogodio se 2008. godine. Tada je su\u010delje Firefox 3 \u201ezalegalo\u201c ako se izvo\u0111ena zapisa na disk velikog broja datoteka. Problem je bila u tome \u0161to se u implementaciji su\u010delja za pohranu informacija o njegovom stanju koristila baza podataka SQLite. Nakon svake promjene koja se dogodila u su\u010delju, pozivala se funkcija <code>fsync()<\/code>, \u0161to je davalo dobra jamstva trajnog pohranjivanja podataka. U tada kori\u0161tenom datote\u010dnom sustavu ext3 funkcija <code>fsync()<\/code> spremala je na disk sve \"prljave\" stranice u sustavu, a ne samo one koje su se odnosile na odre\u0111enu datoteku. To je zna\u010dilo da je klik na gumb u Firefoxu mogao inicirati zapis megabajta podataka na magnetski disk, \u0161to je moglo potrajati i nekoliko sekundi. Rje\u0161enju problema, koliko sam shvatio iz <noindex><a rel=\"nofollow\" href=\"http:\/\/shaver.off.net\/diary\/2008\/05\/25\/fsyncers-and-curveballs\/\">ovoga<\/a><\/noindex> materijala, bilo je potrebno premjestiti rad s bazom podataka u asinkrone pozadinske zadatke. To zna\u010di da su u Firefoxu prije bili implementirani rigorozniji zahtjevi za otpornost pohrane podataka nego \u0161to je to stvarno bilo potrebno, a osobine sustava datoteka ext3 su samo pogor\u0161ale ovaj problem.<\/p>\n<p>Druga neuskla\u0111enost dogodila se 2009. godine. Tada su, nakon kvara sustava, korisnici nove datote\u010dne sustave ext4 nai\u0161li na to da mnoge nedavno stvorene datoteke imaju nulu du\u017einu, a s starijom datote\u010dnom sustavom ext3 to se nije dogodilo. U prethodnom odlomku govorio sam o tome da je ext3 na disk isporu\u010divala previ\u0161e podataka, \u0161to je znatno usporilo rad <code>fsync()<\/code>. Da bi se pobolj\u0161ala situacija, ext4 na disk isporu\u010duje samo one \"prljave\" stranice koje su vezane uz odre\u0111enu datoteku. A podaci drugih datoteka ostaju u memoriji znatno du\u017ee nego kod primjene ext3. Ovo je u\u010dinjeno radi pobolj\u0161anja performansi (po defaultu, podaci ostaju u tom stanju 30 sekundi, to se mo\u017ee podesiti uz pomo\u0107 <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\">ovdje<\/a><\/noindex> mo\u017eete prona\u0107i dodatne materijale o tome). To zna\u010di da se veliki volumen podataka mo\u017ee trajno izgubiti nakon kvara. Rje\u0161enje ovog problema le\u017ei u kori\u0161tenju <code>fsync()<\/code> u aplikacijama koje trebaju osigurati otpornu pohranu podataka i maksimalno ih za\u0161tititi od posljedica kvarova. Funkcija <code>fsync()<\/code> djeluje pri kori\u0161tenju ext4 mnogo u\u010dinkovitije nego pri kori\u0161tenju ext3. Minus ovog pristupa je da njegovo kori\u0161tenje, kao i prije, usporava izvr\u0161enje nekih operacija, poput instalacije programa. Pojedinosti o tome pogledajte <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/322823\/\">ovdje<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/thunk.org\/tytso\/blog\/2009\/03\/12\/delayed-allocation-and-the-zero-length-file-problem\/\">ovdje<\/a><\/noindex>.<\/p>\n<p>Tre\u0107i problem, koji se odnosi na <code>fsync()<\/code>, dogodio se 2018. godine. Tada, u okviru projekta PostgreSQL, otkriveno je da ako funkcija <code>fsync()<\/code> naleti na pogre\u0161ku, ozna\u010dava \"prljave\" stranice kao \"\u010diste\". Kao rezultat toga, sljede\u0107i pozivi <code>fsync()<\/code> ni\u0161ta se ne radi s takvim stranicama. Zbog toga modificirane stranice ostaju u memoriji i nikada se ne zapisuju na disk. To je prava katastrofa, jer \u0107e aplikacija smatrati da su neki podaci zapisani na disku, dok to zapravo ne\u0107e biti tako. Takvi kvarovi <code>fsync()<\/code> javljaju se rijetko, aplikacija u takvim situacijama gotovo ni\u0161ta ne mo\u017ee u\u010diniti za borbu protiv problema. Danas, kada se to dogodi, PostgreSQL i druge aplikacije naglo zavr\u0161avaju s radom. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.usenix.org\/conference\/atc20\/presentation\/rebello\">Ovdje<\/a><\/noindex>, u materijalu \u201eMogu li aplikacije oporaviti se od fsync kvarova?\u201c, ovaj problem se istra\u017euje u svim detaljima. Trenutno je najbolje rje\u0161enje za ovaj problem kori\u0161tenje Direct I\/O s oznakom <code>O_SYNC<\/code> ili s oznakom <code>O_DSYNC<\/code>. Takvim pristupom sustav \u0107e prijaviti gre\u0161ke koje se mogu pojaviti tijekom izvr\u0161avanja odre\u0111enih operacija zapisivanja podataka, ali ovaj pristup zahtijeva da aplikacija samostalno upravlja memorijskim bufferima. Vi\u0161e detalja o tome mo\u017eete pro\u010ditati <noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/752063\/\">ovdje<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Fsync_Errors\">ovdje<\/a><\/noindex>.<\/p>\n<h2>Otvaranje datoteka s oznakama O_SYNC i O_DSYNC<\/h2>\n<p>\nVratimo se raspravi o mehanizmima Linuxa koji osiguravaju pouzdano pohranjivanje podataka. Naime, rije\u010d je o upotrebi oznake <code>O_SYNC<\/code> ili oznake <code>O_DSYNC<\/code> prilikom otvaranja datoteka koriste\u0107i sistemski poziv <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/open.2.html\">open()<\/a><\/noindex>. Takvim pristupom, svaka operacija zapisivanja podataka izvr\u0161ava se tako kao da sustav dobiva, prema tome, naredbe <code>write()<\/code> sustavu daju, odnosno, naredbe <code>fsync()<\/code> i <code>fdatasync()<\/code>. U <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/009695399\/basedefs\/xbd_chap03.html#tag_03_373\">specifikaciji POSIX<\/a><\/noindex> to se naziva \u201eSinhronizirano I\/O zavr\u0161ava cjelovitost datoteke\u201c i \u201eZavr\u0161etak cjelovitosti podataka\u201c. Glavna prednost ovog pristupa je u tome \u0161to je za osiguranje cjelovitosti podataka potreban samo jedan sistemski poziv, a ne dva (na primjer \u2014 <code>write()<\/code> i <code>fdatasync()<\/code>). Glavni nedostatak ovog pristupa je taj \u0161to \u0107e sve operacije zapisivanja koje koriste odgovaraju\u0107i deskriptor datoteke biti sinkronizirane, \u0161to mo\u017ee ograni\u010diti mogu\u0107nosti strukturiranja koda aplikacije.<\/p>\n<h2>Kori\u0161tenje Direct I\/O s oznakom O_DIRECT<\/h2>\n<p>\nSistem poziv <code>open()<\/code> podr\u017eava oznaku <code>O_DIRECT<\/code>, koja je namijenjena za to da, zaobi\u0161av\u0161i cache operativnog sustava, izvr\u0161ava operacije ulaz\/izlaz, direktno komuniciraju\u0107i s diskom. To, u mnogim slu\u010dajevima, zna\u010di da \u0107e naredbe zapisivanja koje izdaje program biti direktno prenesene u naredbe usmjerene na rad s diskom. No, op\u0107enito, ovaj mehanizam nije zamjena za funkcije <code>fsync()<\/code> ili <code>fdatasync()<\/code>. Naime, sam disk mo\u017ee <noindex><a rel=\"nofollow\" href=\"https:\/\/www.evanjones.ca\/durability-nvme.html\">odlo\u017eiti ili ke\u0161irati<\/a><\/noindex> odgovaraju\u0107e komande za zapis podataka. I, \u0161to je jo\u0161 gore, u nekim posebnim slu\u010dajevima operacije ulaza-izlaza izvr\u0161ene upotrebom oznake <code>O_DIRECT<\/code>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ext4.wiki.kernel.org\/index.php\/Clarifying_Direct_IO%27s_Semantics\">se prenose<\/a><\/noindex> na tradicionalne buferizirane operacije. Najlak\u0161e je rije\u0161iti ovaj problem koriste\u0107i za otvaranje datoteka i oznaku <code>O_DSYNC<\/code>, \u0161to \u0107e zna\u010diti da za svaku operaciju zapisivanja slijedi poziv <code>fdatasync()<\/code>.<\/p>\n<p>Ispostavilo se da je u datote\u010dnom sustavu XFS nedavno dodan \u201ebrzi put\u201c za <code>O_DIRECT|O_DSYNC<\/code>-zapis podataka. Ako se prepisuje blok koriste\u0107i <code>O_DIRECT|O_DSYNC<\/code>, tada XFS, umjesto da isprazni ke\u0161, izvr\u0161it \u0107e FUA-zapisnu naredbu u slu\u010daju da ure\u0111aj to podr\u017eava. To sam potvrdio koriste\u0107i alat <code>blktrace<\/code> u sustavu Linux 5.4\/Ubuntu 20.04. Ovaj pristup trebao bi biti u\u010dinkovitiji, jer se pri njemu na disk zapisuje minimalna koli\u010dina podataka, a pritom se koristi jedna operacija, a ne dvije (zapis i ispu\u0161tanje ke\u0161a). Prona\u0161ao sam poveznicu na <noindex><a rel=\"nofollow\" href=\"https:\/\/patchwork.kernel.org\/patch\/10250257\/\">zakrpa<\/a><\/noindex> jezgru iz 2018. godine koja implementira ovaj mehanizam. Tu se raspravlja o primjeni ove optimizacije i u drugim datote\u010dnim sustavima, ali koliko mi je poznato, XFS je trenutno jedini datote\u010dni sustav koji to podr\u017eava.<\/p>\n<h2>Funkcija sync_file_range()<\/h2>\n<p>\nU Linuxu postoji sistemski poziv <noindex><a rel=\"nofollow\" href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/sync_file_range.2.html\">sync_file_range()<\/a><\/noindex>, koji omogu\u0107uje ispu\u0161tanje na disk samo dijela datoteke, a ne cijele datoteke. Ovaj poziv pokre\u0107e asinhrono ispu\u0161tanje podataka i ne \u010deka njegovo dovr\u0161avanje. No, u priru\u010dniku za <code>sync_file_range()<\/code> stoji da je ova naredba \u201evrlo opasna\u201c. Preporu\u010duje se da se s njom ne koristi. Karakteristike i opasnosti <code>sync_file_range()<\/code> vrlo su dobro opisane u <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2014\/03\/how-syncfilerange-really-works.html\">ovom<\/a><\/noindex> materijalu. Konkretno, o\u010dito, ovaj poziv koristi RocksDB za upravljanje vremenom kada jezgra ispu\u0161ta \u201eprljave\u201c podatke na disk. Ali pritom se koristi i <code>fdatasync()<\/code>. U <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/rocksdb\/search?q=sync_file_range\">kodu<\/a><\/noindex> RocksDB ima zanimljive komentare na tu temu. Na primjer, \u010dini se da poziv <code>sync_file_range()<\/code> prilikom kori\u0161tenja ZFS ne dovodi do ispu\u0161tanja podataka na disk. Iskustvo mi govori da kod koji se rijetko koristi, mo\u017ee sadr\u017eavati gre\u0161ke. Stoga bih preporu\u010dio da se ovaj sistemski poziv ne koristi bez krajnje nu\u017ede.<\/p>\n<h2>Sistemski pozivi koji poma\u017eu osigurati trajno \u010duvanje podataka<\/h2>\n<p>\nDo\u0161ao sam do zaklju\u010dka da se za izvo\u0111enje ulazno\/izlaznih operacija koje osiguravaju pouzdano \u010duvanje podataka mogu koristiti tri pristupa. Svi oni zahtijevaju pozivanje funkcije <code>fsync()<\/code> za direktorij u kojem je datoteka stvorena. Evo tih pristupa:<\/p>\n<ol>\n<li>Poziv funkcije <code>fdatasync()<\/code> ili <code>fsync()<\/code> nakon funkcije <code>write()<\/code> (bolje koristiti <code>fdatasync()<\/code>).<\/li>\n<li>Rad s opisnikom datoteke otvorenim s zastavicom <code>O_DSYNC<\/code> ili <code>O_SYNC<\/code> (bolje \u2014 s zastavicom <code>O_DSYNC<\/code>).<\/li>\n<li>Kori\u0161tenje naredbe <code>pwritev2()<\/code> s oznakom <code>RWF_DSYNC<\/code> ili <code>RWF_SYNC<\/code> (preferabilno \u2014 s zastavicom <code>RWF_DSYNC<\/code>).<\/li>\n<\/ol>\n<p><\/p>\n<h2>Bilje\u0161ke o performansama<\/h2>\n<p>\nNisam se bavio detaljnim mjerenjem performansi razli\u010ditih mehanizama koje sam istra\u017eivao. Primije\u0107ene razlike u brzini njihovog rada su vrlo male. To zna\u010di da se mogu varati, a to \u0161to pod drugim uvjetima isto mo\u017ee dati druge rezultate. Prvo \u0107u govoriti o onome \u0161to sna\u017enije utje\u010de na performanse, a zatim o onome \u0161to manje utje\u010de.<\/p>\n<ol>\n<li>Ponovno pisanje podataka u datoteku je br\u017ee od pridru\u017eivanja podataka datoteci (dobitak u performansama mo\u017ee iznositi 2-100%). Pridru\u017eivanje podataka datoteci zahtijeva dodatne promjene u metapodacima datoteke, \u010dak i nakon sistemskog poziva <code>fallocate()<\/code>, ali razmjeri ovog u\u010dinka se mogu mijenjati. Preporu\u010dujem, za osiguranje najboljih performansi, pozivanje <code>fallocate()<\/code> za prethodno dodjeljivanje potrebnog prostora. Nakon toga, taj prostor treba izri\u010dito ispuniti nulama i pozvati <code>fsync()<\/code>. Time \u0107e odgovaraju\u0107i blokovi u datote\u010dnom sustavu biti ozna\u010deni kao \u201edodijeljeni\u201c, a ne kao \u201eneodre\u0111eni\u201c. To daje malo (oko 2%) pobolj\u0161anje performansi. Osim toga, kod nekih diskova prva operacija pristupa bloku mo\u017ee se izvoditi sporije od drugih. To zna\u010di da punjenje prostora nulama mo\u017ee dovesti do zna\u010dajnog (oko 100%) pobolj\u0161anja performansi. Konkretno, to se mo\u017ee dogoditi s diskovima <noindex><a rel=\"nofollow\" href=\"https:\/\/n2ws.com\/blog\/how-to-guides\/pre-warm-ebs-volumes-on-aws\">AWS EBS<\/a><\/noindex> (to su neovisni podaci, nisam ih mogao potvrditi). Isto vrijedi i za skladi\u0161ta <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/compute\/docs\/disks\/benchmarking-pd-performance\">GCP Persistent Disk<\/a><\/noindex> (a ovo su ve\u0107 slu\u017ebene informacije, potvr\u0111ene ispitivanjima). Drugi stru\u010dnjaci su napravili sli\u010dna <noindex><a rel=\"nofollow\" href=\"http:\/\/yoshinorimatsunobu.blogspot.com\/2009\/05\/overwriting-is-much-faster-than_28.html\">zapa\u017eanja<\/a><\/noindex>, koja se odnose na razli\u010dite diskove.<\/li>\n<li>\u0160to je manje sistemskih poziva \u2014 to su ve\u0107e performanse (dobitak mo\u017ee biti oko 5%). \u010cini se da je poziv <code>open()<\/code> s oznakom <code>O_DSYNC<\/code> ili poziv <code>pwritev2()<\/code> s oznakom <code>RWF_SYNC<\/code> br\u017ei od poziva <code>fdatasync()<\/code>Sumnjam da je razlog u tome \u0161to se takvim pristupom smanjuje broj sistemskih poziva potrebnih za rje\u0161avanje iste zada\u0107e (jedan poziv umjesto dva). No, razlika u performansama je vrlo mala, stoga to mo\u017eete zanemariti i koristiti u aplikaciji ono \u0161to ne\u0107e komplikovati njezinu logiku.<\/li>\n<\/ol>\n<p>\nAko vas zanima tema odr\u017eivog pohranjivanja podataka \u2014 evo nekoliko korisnih materijala:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.scylladb.com\/2017\/10\/05\/io-access-methods-scylla\/\">I\/O metode pristupa<\/a><\/noindex> \u2014 pregled osnovnih mehanizama ulaza\/izlaza.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/457667\/\">Osiguravanje da podaci stignu na disk<\/a><\/noindex> \u2014 pri\u010da o tome \u0161to se doga\u0111a s podacima na putu od aplikacije do diska.<\/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\">Kada biste trebali izvr\u0161iti fsync u mati\u010dnom direktoriju<\/a><\/noindex> \u2014 odgovor na pitanje kada treba primijeniti <code>fsync()<\/code> za direktorije. Ako to sa\u017ememo u dvije re\u010denice, trebate to raditi prilikom stvaranja novog datoteke, a razlog ove preporuke je taj \u0161to u Linuxu mo\u017ee biti mnogo referenci na istu datoteku.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/bobsql.com\/sql-server-on-linux-forced-unit-access-fua-internals\/\">SQL Server na Linuxu: FUA unutarnjost<\/a><\/noindex> \u2014 ovdje je opisano kako je odr\u017eivo pohranjivanje podataka implementirano u SQL Serveru na Linux platformi. Ovdje su prikakazne zanimljive usporedbe izme\u0111u sistemskih poziva na Windows-u i Linux-u. Gotovo sam siguran da sam zahvaljuju\u0107i ovom materijalu saznao o FUA optimizaciji XFS.<\/li>\n<\/ul>\n<p>\nJeste li ikada izgubili podatke koje ste smatrali sigurno pohranjene na disku?<\/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=\"Odr\u017eivo pohranjivanje podataka i Linux API-ji za datoteke\" 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=\"Odr\u017eivo pohranjivanje podataka i Linux API-ji za datoteke\" src=\"\/wp-content\/uploads\/2020\/10\/d9fd0b1c09eb6e40944aee2d13ee4088.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Izvor: <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.4 - 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\/hr\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\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\/hr\/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 Odr\u017eivo pohranjivanje podataka i Linux datote\u010dni API | ProHoster","description":"Istra\u017euju\u0107i otpornost pohranjivanja podataka u cloud sustavima, odlu\u010dio sam provjeriti sebe i uvjeriti se da razumijem osnovne koncepte.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/ustojchivoe-hranenie-dannyh-i-fajlovye-api-linux","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","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\/hr\/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\/hr\/wp-json\/wp\/v2\/posts\/98090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=98090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/98090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/98091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=98090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=98090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=98090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}