Ħażna ta' Dejta Durabbli u APIs tal-Fajl Linux

Waqt ir-riċerka dwar is-sostenibbiltà tal-ħażna tad-dejta fis-sistemi tal-cloud, iddeċidejt li nittestja lili nnifsi biex niżgura li fhimt l-affarijiet bażiċi. I beda billi taqra l-ispeċifikazzjoni NVMe sabiex nifhmu liema garanziji rigward il-ħażna tad-dejta sostenibbli (jiġifieri, garanziji li d-dejta tkun disponibbli wara ħsara fis-sistema) jagħtuna diski NMVe. Għamilt il-konklużjonijiet ewlenin li ġejjin: id-dejta għandha titqies bħala ħsara mill-mument li jingħata l-kmand biex tikteb id-dejta sal-mument li tinkiteb fil-mezz tal-ħażna. Madankollu, ħafna mill-programmi pjuttost kuntenti jużaw sejħiet tas-sistema biex jirreġistraw id-data.

F'din il-kariga, nesplora l-mekkaniżmi ta 'ħażna persistenti pprovduti mill-APIs tal-fajls Linux. Jidher li kollox għandu jkun sempliċi hawn: il-programm isejjaħ il-kmand write(), u wara li dan il-kmand jitlesta, id-dejta tiġi ssejvjata b'mod sigur fuq id-diska. Iżda write() tikkopja biss id-dejta tal-applikazzjoni fil-cache tal-kernel li tinsab fir-RAM. Sabiex iġiegħel is-sistema tikteb id-data fuq id-disk, għandek bżonn tuża xi mekkaniżmi addizzjonali.

Ħażna ta' Dejta Durabbli u APIs tal-Fajl Linux

B’mod ġenerali, dan il-materjal huwa ġabra ta’ noti relatati ma’ dak li tgħallimt fuq suġġett ta’ interess għalija. Jekk nitkellmu fil-qosor ħafna dwar l-iktar ħaġa importanti, jirriżulta li biex torganizza ħażna sostenibbli tad-dejta trid tuża l-kmand fdatasync() jew tiftaħ fajls bil-bandiera O_DSYNC. Jekk int interessat li titgħallem aktar dwar x'jiġri mid-data fi triqitha mill-kodiċi għad-diska, agħti ħarsa lejn dan artikolu.

Karatteristiċi tal-użu tal-funzjoni write().

Sejħa tas-sistema write() definiti fl-istandard IEEE POSIX bħala tentattiv biex tikteb data f'deskrittur tal-fajl. Wara t-tlestija b'suċċess write() L-operazzjonijiet tal-qari tad-dejta għandhom jirritornaw eżattament il-bytes li kienu miktuba qabel, u jagħmlu dan anke jekk id-dejta tiġi aċċessata minn proċessi jew ħjut oħra (hawn sezzjoni rilevanti tal-istandard POSIX). Hawnhekk, fit-taqsima dwar kif il-ħjut jinteraġixxu ma' operazzjonijiet normali tal-fajl, hemm nota li tgħid li jekk żewġ ħjut kull wieħed isejjaħ dawn il-funzjonijiet, allura kull sejħa trid tara jew il-konsegwenzi kollha magħżula tas-sejħa l-oħra, jew l-ebda waħda. konsegwenzi. Dan iwassal għall-konklużjoni li l-operazzjonijiet kollha tal-I/O tal-fajls għandhom iżommu lock fuq ir-riżorsa li qed joperaw fuqha.

Dan ifisser li l-operazzjoni write() huwa atomiku? Mil-lat tekniku, iva. L-operazzjonijiet tal-qari tad-dejta jridu jirritornaw dak kollu jew xejn minn dak li nkiteb bih write(). Iżda l-operazzjoni write(), skond l-istandard, mhux bilfors irid jintemm billi jikteb dak kollu li kien mitlub li jikteb. Hija permessa tikteb biss parti mid-data. Per eżempju, jista 'jkollna żewġ ħjut kull wieħed jehmeż 1024 bytes ma' fajl deskritt mill-istess deskrittur tal-fajl. Mil-lat tal-istandard, riżultat aċċettabbli se jkun meta kull operazzjoni ta 'kitba tista' tehmeż byte wieħed biss mal-fajl. Dawn l-operazzjonijiet se jibqgħu atomiċi, iżda wara li jitlestew, id-dejta li kitbu fil-fajl se titħallat. Hawnhekk diskussjoni interessanti ħafna dwar dan is-suġġett dwar Stack Overflow.

Funzjonijiet fsync() u fdatasync().

L-eħfef mod biex titlaħla d-data fuq disk huwa li ssejjaħ il-funzjoni fsync(). Din il-funzjoni titlob lis-sistema operattiva biex tittrasferixxi l-blokki kollha modifikati mill-cache għad-diska. Dan jinkludi l-metadata tal-fajl kollha (ħin ta 'aċċess, ħin ta' modifika tal-fajl, eċċ). Nemmen li din il-metadata rari hija meħtieġa, allura jekk taf li mhix importanti għalik, tista 'tuża l-funzjoni fdatasync(). Fil għajnuna fuq fdatasync() jingħad li waqt it-tħaddim ta 'din il-funzjoni, tali ammont ta' metadejta jiġi ffrankat fuq disk li huwa "meħtieġ għall-eżekuzzjoni korretta tal-operazzjonijiet ta 'qari tad-dejta li ġejjin." U dan huwa eżattament dak li jimpurtahom ħafna mill-applikazzjonijiet.

Problema waħda li tista' tqum hawnhekk hija li dawn il-mekkaniżmi ma jiggarantixxux li l-fajl ikun jista' jiġi skopert wara falliment possibbli. B'mod partikolari, meta toħloq fajl ġdid, trid iċempel fsync() għad-direttorju li fih. Inkella, wara falliment, jista 'jirriżulta li dan il-fajl ma jeżistix. Ir-raġuni għal dan hija li f'UNIX, minħabba l-użu ta 'hard links, fajl jista' jeżisti f'diversi direttorji. Għalhekk, meta ċċempel fsync() m'hemm l-ebda mod biex fajl ikun jaf liema data tad-direttorju għandha titlaħlaħ ukoll fuq disk (hawn Tista' taqra aktar dwar dan). Jidher li s-sistema tal-fajls ext4 hija kapaċi awtomatikament japplikaw fsync() għad-direttorji li fihom il-fajls korrispondenti, iżda dan jista' ma jkunx il-każ b'sistemi ta' fajls oħra.

Dan il-mekkaniżmu jista' jiġi implimentat b'mod differenti fuq sistemi ta' fajls differenti. jien kont blktrace biex titgħallem dwar liema operazzjonijiet tad-disk jintużaw fis-sistemi tal-fajls ext4 u XFS. It-tnejn joħorġu kmandi regolari tal-kitba fuq id-disk kemm għall-kontenut tal-fajl kif ukoll għall-ġurnal tas-sistema tal-fajls, laħlaħ il-cache, u joħorġu billi jwettqu FUA (Force Unit Access, kitba tad-dejta direttament fuq id-disk, billi tneħħi l-cache) tikteb fil-ġurnal. Probabbilment jagħmlu dan sabiex jikkonfermaw li t-tranżazzjoni seħħet. Fuq drives li ma jappoġġjawx FUA, dan jikkawża żewġ fwawar tal-cache. L-esperimenti tiegħi wrew dan fdatasync() ftit aktar malajr fsync(). Utilità blktrace jindika li fdatasync() normalment jikteb inqas data fuq disk (f'ext4 fsync() jikteb 20 KiB, u fdatasync() - 16 KiB). Ukoll, sibt li XFS huwa kemmxejn aktar mgħaġġel minn ext4. U hawn bl-għajnuna blktrace irnexxielhom issir taf li fdatasync() flushes inqas data fuq disk (4 KiB f'XFS).

Sitwazzjonijiet ambigwi li jinqalgħu meta tuża fsync()

Kapaċi naħseb fi tliet sitwazzjonijiet ambigwi rigward fsync()li ltqajt magħhom fil-prattika.

L-ewwel każ bħal dan seħħ fl-2008. Imbagħad l-interface Firefox 3 ffriżat jekk numru kbir ta 'fajls kienu miktuba fuq disk. Il-problema kienet li l-implimentazzjoni tal-interface użat database SQLite biex taħżen informazzjoni dwar l-istat tagħha. Wara kull bidla li seħħet fl-interface, il-funzjoni kienet imsejħa fsync(), li ta garanziji tajbin ta 'ħażna ta' data stabbli. Fis-sistema tal-fajl ext3 imbagħad użata, il-funzjoni fsync() iddampjat il-paġni kollha "maħmuġin" fis-sistema fuq disk, u mhux biss dawk li kienu relatati mal-fajl korrispondenti. Dan kien ifisser li meta tikklikkja buttuna f'Firefox tista' twassal biex jinkitbu megabytes ta' data fuq disk manjetiku, li jista' jieħu ħafna sekondi. Is-soluzzjoni għall-problema, sa fejn nifhem jien ta 'dan materjal kien li tittrasferixxi xogħol mad-database għal ħidmiet ta 'sfond mhux sinkroniku. Dan ifisser li Firefox qabel implimenta rekwiżiti ta 'ħażna aktar stretti milli kien verament meħtieġ, u l-karatteristiċi tas-sistema tal-fajls ext3 biss aggravaw din il-problema.

It-tieni problema seħħet fl-2009. Imbagħad, wara ħabta tas-sistema, l-utenti tas-sistema l-ġdida tal-fajls ext4 kienu ffaċċjati bil-fatt li ħafna fajls maħluqa ġodda kellhom tul żero, iżda dan ma ġarax bis-sistema tal-fajls ext3 eqdem. Fil-paragrafu preċedenti, tkellimt dwar kif ext3 laħlaħ wisq dejta fuq disk, li naqqset ħafna l-affarijiet. fsync(). Biex tittejjeb is-sitwazzjoni, f'ext4 biss dawk il-paġni maħmuġin li huma rilevanti għal fajl partikolari jiġu mlaħalħa fuq disk. U data minn fajls oħra tibqa' fil-memorja għal żmien ħafna itwal milli b'ext3. Dan sar biex titjieb il-prestazzjoni (b'mod awtomatiku, id-dejta tibqa' f'dan l-istat għal 30 sekonda, tista' tikkonfigura dan billi tuża dirty_expire_centisecs; hawn Tista 'ssib materjali addizzjonali dwar dan). Dan ifisser li ammont kbir ta 'dejta tista' tintilef b'mod irrimedjabbli wara falliment. Is-soluzzjoni għal din il-problema hija li tuża fsync() f'applikazzjonijiet li jeħtieġu li jiżguraw ħażna stabbli tad-dejta u jipproteġuhom kemm jista 'jkun mill-konsegwenzi ta' fallimenti. Funzjoni fsync() jaħdem ħafna aktar effiċjenti meta tuża ext4 milli meta tuża ext3. L-iżvantaġġ ta 'dan l-approċċ huwa li l-użu tiegħu, bħal qabel, inaqqas l-eżekuzzjoni ta' xi operazzjonijiet, bħall-installazzjoni ta 'programmi. Ara d-dettalji dwar dan hawn и hawn.

It-tielet problema rigward fsync(), oriġinaw fl-2018. Imbagħad, fil-qafas tal-proġett PostgreSQL, instab li jekk il-funzjoni fsync() tiltaqa' ma' żball, timmarka paġni "maħmuġin" bħala "nodfa". Bħala riżultat, is-sejħiet li ġejjin fsync() Ma jagħmlu xejn b'paġni bħal dawn. Minħabba dan, paġni modifikati huma maħżuna fil-memorja u qatt ma jinkitbu fuq disk. Dan huwa diżastru reali, peress li l-applikazzjoni se taħseb li xi dejta tinkiteb fuq id-diska, iżda fil-fatt mhux se jkun. Nuqqasijiet bħal dawn fsync() huma rari, l-applikazzjoni f'sitwazzjonijiet bħal dawn tista 'tagħmel kważi xejn biex tiġġieled il-problema. Dawn il-ġranet, meta jiġri dan, PostgreSQL u applikazzjonijiet oħra jiġġarrfu. Hawnhekk, fil-materjal "Jistgħu l-Applikazzjonijiet Jirkupraw minn Ħsarat fsync?", Din il-problema hija esplorata fid-dettall. Bħalissa l-aħjar soluzzjoni għal din il-problema hija li tuża Direct I/O mal-bandiera O_SYNC jew bi bandiera O_DSYNC. B'dan l-approċċ, is-sistema tirrapporta żbalji li jistgħu jseħħu waqt operazzjonijiet ta 'kitba speċifiċi, iżda dan l-approċċ jeħtieġ li l-applikazzjoni timmaniġġja l-buffers hija stess. Aqra aktar dwar dan hawn и hawn.

Jiftħu fajls bl-użu tal-bnadar O_SYNC u O_DSYNC

Ejja nerġgħu lura għad-diskussjoni tal-mekkaniżmi Linux li jipprovdu ħażna ta 'dejta stabbli. Jiġifieri, qed nitkellmu dwar l-użu tal-bandiera O_SYNC jew bandiera O_DSYNC meta tiftaħ fajls bl-użu tas-sejħa tas-sistema miftuħa (). B'dan l-approċċ, kull operazzjoni ta 'kitba tad-dejta titwettaq bħallikieku wara kull kmand write() is-sistema tingħata kmandi kif xieraq fsync() и fdatasync(). Fil speċifikazzjonijiet POSIX dan jissejjaħ "Synchronized I/O File Integrity Completion" u "Data Integrity Completion". Il-vantaġġ ewlieni ta 'dan l-approċċ huwa li biex tiġi żgurata l-integrità tad-dejta, għandek bżonn biss tagħmel sejħa waħda tas-sistema, aktar milli tnejn (per eżempju - write() и fdatasync()). L-iżvantaġġ ewlieni ta 'dan l-approċċ huwa li l-kitbiet kollha li jużaw id-deskrittur tal-fajl korrispondenti se jkunu sinkronizzati, li jista' jillimita l-abbiltà li tiġi strutturata l-kodiċi tal-applikazzjoni.

Uża Direct I/O bil-bandiera O_DIRECT

Sejħa tas-sistema open() jappoġġja bandiera O_DIRECT, li hija mfassla biex tevita l-cache tas-sistema operattiva biex twettaq operazzjonijiet I/O billi jinteraġixxi direttament mad-diska. Dan, f'ħafna każijiet, ifisser li l-kmandi tal-kitba maħruġa mill-programm jiġu tradotti direttament fi kmandi mmirati biex jaħdmu mad-diska. Iżda, b'mod ġenerali, dan il-mekkaniżmu mhuwiex sostitut għall-funzjonijiet fsync() jew fdatasync(). Il-fatt hu li d-disk innifsu jista ' jiddeferixxi jew cache kmandi korrispondenti tal-kitba tad-data. U, biex tgħaxxaq, f'xi każijiet speċjali l-operazzjonijiet tal-I/O saru meta tuża l-bandiera O_DIRECT, xandira f'operazzjonijiet tradizzjonali buffered. L-eħfef mod biex issolvi din il-problema huwa li tuża l-bandiera biex tiftaħ fajls O_DSYNC, li se jfisser li kull operazzjoni ta 'kitba tkun segwita minn sejħa fdatasync().

Irriżulta li s-sistema tal-fajl XFS reċentement żiedet "mogħdija mgħaġġla" għal O_DIRECT|O_DSYNC-reġistrazzjoni tad-data. Jekk blokka tinkiteb mill-ġdid bl-użu O_DIRECT|O_DSYNC, imbagħad XFS, minflok ma jiflaħ il-cache, se jesegwixxi l-kmand tal-kitba FUA jekk l-apparat jappoġġjah. I vverifikajt dan billi użajt l-utilità blktrace fuq sistema Linux 5.4/Ubuntu 20.04. Dan l-approċċ għandu jkun aktar effiċjenti, peress li meta jintuża, jinkiteb ammont minimu ta' data fuq id-diska u tintuża operazzjoni waħda, aktar milli tnejn (kitba u flushing tal-cache). Sibt link għal garża 2018 kernel, li jimplimenta dan il-mekkaniżmu. Hemm xi diskussjoni hemmhekk dwar l-applikazzjoni ta 'din l-ottimizzazzjoni għal sistemi ta' fajls oħra, iżda sa fejn naf jien, XFS hija l-unika sistema ta 'fajls li tappoġġja dan s'issa.

sync_file_range() funzjoni

Linux għandu sistema ta 'sejħa sync_file_range (), li jippermettilek li tlaħlaħ biss parti mill-fajl fuq disk, aktar milli l-fajl kollu. Din is-sejħa tibda flush tad-dejta mhux sinkroniku u ma tistenniex biex titlesta. Iżda fiċ-ċertifikat sync_file_range() it-tim jingħad li hu “perikoluż ħafna”. Mhux rakkomandat li tużah. Karatteristiċi u perikli sync_file_range() deskritt tajjeb ħafna fi dan materjal. Speċifikament, din is-sejħa tidher li tuża RocksDB biex tikkontrolla meta l-qalba tiflaħ id-dejta maħmuġa fuq id-diska. Iżda fl-istess ħin, biex tiġi żgurata ħażna ta 'dejta stabbli, tintuża wkoll fdatasync(). Fil kodiċi RocksDB għandu xi kummenti interessanti dwar dan is-suġġett. Per eżempju, jidher li s-sejħa sync_file_range() Meta tuża ZFS, ma flush data fuq disk. L-esperjenza tgħidli li kodiċi li rarament jintuża x'aktarx ikun fih bugs. Għalhekk, nagħti parir li ma tużax din is-sejħa tas-sistema sakemm ma jkunx assolutament meħtieġ.

Sejħiet tas-sistema li jgħinu biex jiżguraw il-persistenza tad-dejta

Wasalt għall-konklużjoni li hemm tliet approċċi li jistgħu jintużaw biex iwettqu operazzjonijiet I/O li jiżguraw il-persistenza tad-dejta. Kollha jeħtieġu sejħa tal-funzjoni fsync() għad-direttorju li fih inħoloq il-fajl. Dawn huma l-approċċi:

  1. Sejħa funzjoni fdatasync() jew fsync() wara l-funzjoni write() (huwa aħjar li tuża fdatasync()).
  2. Ħidma b'deskrittur tal-fajl miftuħ b'bandiera O_DSYNC jew O_SYNC (aħjar - bil-bandiera O_DSYNC).
  3. Bl-użu tal-kmand pwritev2() bil-bandiera RWF_DSYNC jew RWF_SYNC (preferibbilment b'bandiera RWF_DSYNC).

Noti ta' Prestazzjoni

Jien ma tkejjel bir-reqqa l-prestazzjoni tad-diversi mekkaniżmi li eżaminajt. Id-differenzi li ndunajt fil-ħeffa tax-xogħol tagħhom huma żgħar ħafna. Dan ifisser li nista’ nkun żbaljat, u li taħt kundizzjonijiet differenti l-istess ħaġa tista’ tipproduċi riżultati differenti. L-ewwel, se nitkellem dwar dak li jaffettwa l-prestazzjoni aktar, u mbagħad dak li jaffettwa l-prestazzjoni inqas.

  1. Il-kitba fuq il-fajl tad-dejta hija aktar mgħaġġla milli t-twaħħil tad-dejta ma 'fajl (il-benefiċċju tal-prestazzjoni jista' jkun 2-100%). It-twaħħil tad-dejta ma' fajl jeħtieġ bidliet addizzjonali fil-metadejta tal-fajl, anke wara sejħa tas-sistema fallocate(), iżda l-kobor ta 'dan l-effett jista' jvarja. Nirrakkomanda, għall-aħjar prestazzjoni, li ċċempel fallocate() biex jalloka minn qabel l-ispazju meħtieġ. Imbagħad dan l-ispazju għandu jimtela b'mod espliċitu b'żerijiet u msejjaħ fsync(). Dan jiżgura li l-blokki korrispondenti fis-sistema tal-fajls ikunu mmarkati bħala "allokati" aktar milli "mhux allokati". Dan jagħti titjib żgħir (madwar 2%) fil-prestazzjoni. Barra minn hekk, xi diski jista 'jkollhom l-ewwel aċċess aktar bil-mod għal blokk minn oħrajn. Dan ifisser li l-mili tal-ispazju b'żerijiet jista 'jwassal għal titjib sinifikanti (madwar 100%) fil-prestazzjoni. B'mod partikolari, dan jista 'jiġri bid-diski AWS EBS (din hija data mhux uffiċjali, ma stajtx nikkonfermaha). L-istess jgħodd għall-ħażna Disk Persistenti tal-GCP (u din hija diġà informazzjoni uffiċjali, ikkonfermata minn testijiet). Esperti oħra għamlu l-istess osservazzjoni, relatati ma 'diversi diski.
  2. Inqas is-sistema sejħiet, iktar ikun għoli l-prestazzjoni (il-qligħ jista 'jkun ta' madwar 5%). Tidher qisha sfida open() bil-bandiera O_DSYNC jew ċempel pwritev2() bil-bandiera RWF_SYNC aktar mgħaġġel minn sejħa fdatasync(). Nissuspetta li l-punt hawnhekk huwa li dan l-approċċ għandu rwol fil-fatt li għandhom isiru inqas sejħiet tas-sistema biex issolvi l-istess problema (sejħa waħda minflok tnejn). Iżda d-differenza fil-prestazzjoni hija żgħira ħafna, għalhekk tista 'tinjoraha kompletament u tuża xi ħaġa fl-applikazzjoni li mhux se tikkomplika l-loġika tagħha.

Jekk inti interessat fis-suġġett tal-ħażna tad-dejta sostenibbli, hawn xi materjali utli:

  • Metodi ta 'aċċess I/O — ħarsa ġenerali lejn il-baŜi tal-mekkaniżmi ta' input/output.
  • L-iżgurar tad-data tasal id-disk — storja dwar x'jiġri mid-dejta fit-triq mill-applikazzjoni għad-diska.
  • Meta għandek fsync id-direttorju li jkun fih - it-tweġiba għall-mistoqsija ta' meta tuża fsync() għad-direttorji. Biex tpoġġi dan fil-qosor, jirriżulta li għandek bżonn tagħmel dan meta toħloq fajl ġdid, u r-raġuni għal din ir-rakkomandazzjoni hija li fil-Linux jista 'jkun hemm ħafna referenzi għall-istess fajl.
  • SQL Server fuq Linux: Interni FUA — hawn deskrizzjoni ta' kif il-ħażna persistenti tad-dejta hija implimentata f'SQL Server fuq il-pjattaforma Linux. Hemm xi paraguni interessanti bejn is-sejħiet tas-sistema Windows u Linux hawn. Jien kważi ċert li kien grazzi għal dan il-materjal li tgħallimt dwar l-ottimizzazzjoni FUA ta 'XFS.

Tlift data li ħsibt li kienet maħżuna b'mod sigur fuq disk?

Ħażna ta' Dejta Durabbli u APIs tal-Fajl Linux

Ħażna ta' Dejta Durabbli u APIs tal-Fajl Linux

Sors: www.habr.com