Ma'ajiyar Bayanai Mai Dorewa da APIs Fayil na Linux

Ni, bincikar kwanciyar hankali na ajiyar bayanai a cikin tsarin girgije, na yanke shawarar gwada kaina, don tabbatar da cewa na fahimci abubuwa masu mahimmanci. I fara ta hanyar karanta NVMe spec don fahimtar menene garanti game da dagewar bayanai (wato, garantin cewa bayanan za su kasance bayan gazawar tsarin) suna ba mu diski na NMVe. Na yi babban yanke shawara mai zuwa: kuna buƙatar la'akari da bayanan da suka lalace tun lokacin da aka ba da umarnin rubuta bayanan, kuma har zuwa lokacin da aka rubuta su zuwa matsakaicin ajiya. Koyaya, a yawancin shirye-shiryen, ana amfani da kiran tsarin cikin aminci don rubuta bayanai.

A cikin wannan labarin, na bincika hanyoyin dagewa da APIs fayil ɗin Linux ke bayarwa. Da alama cewa duk abin da ya kamata ya zama mai sauƙi a nan: shirin ya kira umarnin write(), kuma bayan an gama aikin wannan umarni, za a adana bayanan cikin aminci a faifai. Amma write() kawai kwafin bayanan aikace-aikacen zuwa cache kernel dake cikin RAM. Domin tilasta tsarin rubuta bayanai zuwa faifai, dole ne a yi amfani da wasu ƙarin hanyoyin.

Ma'ajiyar Bayanai Mai Dorewa da APIs Fayil na Linux

Gabaɗaya, wannan abu saitin bayanin kula ne da ya danganci abin da na koya akan wani batu mai ban sha'awa a gare ni. Idan muka yi magana a taƙaice game da mafi mahimmanci, ya bayyana cewa don tsara ma'auni mai ɗorewa, kuna buƙatar amfani da umarnin. fdatasync() ko buɗe fayiloli tare da tuta O_DSYNC. Idan kuna sha'awar ƙarin koyo game da abin da ke faruwa da bayanai akan hanya daga lamba zuwa faifai, duba wannan labarin.

Fasalolin amfani da aikin rubuta().

Kiran tsarin write() bayyana a cikin ma'auni IEEE POSIX a matsayin yunƙurin rubuta bayanai zuwa mai bayanin fayil. Bayan nasarar kammala aikin write() Ayyukan karanta bayanan dole ne su dawo da daidaitattun bytes waɗanda aka rubuta a baya, yin haka koda ana samun damar bayanan daga wasu matakai ko zaren (ga shi daidai sashe na ma'aunin POSIX). Yana da, a cikin sashin mu’amalar zaren da ayyukan file na al’ada, akwai bayanin da ke cewa idan zaren guda biyu kowanne ya kira wadannan ayyuka, to kowane kira dole ne ya ga duk sakamakon da aka nuna wanda aiwatar da daya kiran ke haifarwa, ko kuma. ba gani ko kadan babu wani sakamako. Wannan yana haifar da ƙarshe cewa duk ayyukan I/O fayil dole ne su riƙe kulle akan albarkatun da ake aiki dasu.

Wannan yana nufin cewa aikin write() atomic ba? Daga mahangar fasaha, i. Ayyukan karanta bayanai dole ne su dawo ko dai duka ko babu ɗaya daga cikin abin da aka rubuta da su write(). Amma aikin write(), daidai da ma'auni, ba dole ba ne ya ƙare, bayan rubuta duk abin da aka ce ta rubuta. An ba da izinin rubuta ɓangaren bayanan kawai. Misali, muna iya samun rafukan koguna guda biyu kowanne yana rataye bytes 1024 zuwa fayil ɗin da mai siffanta fayil iri ɗaya ya bayyana. Daga ma'anar ma'auni, sakamakon zai zama karɓuwa lokacin da kowane ɗayan ayyukan rubuta zai iya haɗa byte ɗaya kawai ga fayil ɗin. Waɗannan ayyukan za su kasance atom, amma bayan sun kammala, bayanan da suka rubuta zuwa fayil ɗin za su yi tagumi. a nan Tattaunawa mai ban sha'awa akan wannan batu akan Stack Overflow.

fsync () da fdatasync () ayyuka

Hanya mafi sauƙi don ja da bayanai zuwa faifai ita ce kiran aikin fsync(). Wannan aikin yana buƙatar tsarin aiki don matsar da duk tubalan da aka gyara daga cache zuwa faifai. Wannan ya haɗa da duk metadata na fayil ɗin (lokacin shiga, lokacin gyara fayil, da sauransu). Na yi imani wannan metadata ba a cika buƙata ba, don haka idan kun san ba shi da mahimmanci a gare ku, kuna iya amfani da aikin fdatasync(). A taimako a kan fdatasync() ya ce yayin aikin wannan aikin, ana adana irin wannan adadin metadata zuwa faifai, wanda shine "wajibi ne don aiwatar da daidaitattun ayyukan karatun bayanai masu zuwa." Kuma wannan shine ainihin abin da yawancin aikace-aikacen ke kula da su.

Wata matsala da za ta iya tasowa a nan ita ce waɗannan hanyoyin ba su da garantin cewa za a iya samun fayil ɗin bayan gazawar mai yiwuwa. Musamman, lokacin da aka ƙirƙiri sabon fayil, ya kamata mutum ya kira fsync() ga directory ɗin da ke ɗauke da shi. In ba haka ba, bayan karo, zai iya zama cewa babu wannan fayil ɗin. Dalilin haka shi ne cewa a ƙarƙashin UNIX, saboda amfani da hanyoyin haɗin kai, fayil na iya kasancewa a cikin kundayen adireshi da yawa. Saboda haka, lokacin da ake kira fsync() Babu yadda za a yi fayil ya san wace bayanan directory ya kamata a juyar da su zuwa faifai (a nan za ku iya karanta ƙarin game da wannan). Yana kama da tsarin fayil na ext4 yana iya ta atomatik amfani fsync() zuwa kundin adireshi masu ƙunshe da fayiloli masu kama da juna, amma wannan ƙila ba haka lamarin yake da sauran tsarin fayil ba.

Ana iya aiwatar da wannan tsari daban-daban a cikin tsarin fayil daban-daban. na yi amfani blktrace don koyo game da abin da ake amfani da ayyukan faifai a cikin tsarin fayil na ext4 da XFS. Dukansu suna ba da umarni na yau da kullun na rubutawa zuwa diski don abubuwan da ke cikin fayiloli da mujallar tsarin fayil, ja da cache ɗin kuma fita ta hanyar yin FUA (Ƙarfin Ƙarfafawa, rubuta bayanai kai tsaye zuwa faifai, ketare cache) rubuta zuwa mujallar. Wataƙila suna yin hakan ne kawai don tabbatar da gaskiyar ciniki. A kan tafiyarwa waɗanda basa goyan bayan FUA, wannan yana haifar da cache guda biyu. Gwaje-gwaje na sun nuna hakan fdatasync() da sauri kadan fsync(). Amfani blktrace ya nuna cewa fdatasync() yawanci yana rubuta ƙarancin bayanai zuwa diski (a cikin ext4 fsync() ya rubuta 20 KiB, kuma fdatasync() - 16 KB). Hakanan, na gano cewa XFS yana ɗan sauri fiye da ext4. Kuma a nan tare da taimako blktrace ya iya gano hakan fdatasync() yana fitar da ƙarancin bayanai zuwa faifai (4 KiB a cikin XFS).

Matsaloli masu ma'ana yayin amfani da fsync()

Zan iya tunanin yanayi guda uku da ba su da tabbas game da su fsync()wanda na ci karo da shi a aikace.

Irin wannan lamari na farko ya faru ne a shekara ta 2008. A waccan lokacin, ƙirar Firefox 3 ta “daskararre” idan ana rubuta adadin fayiloli zuwa faifai. Matsalar ita ce aiwatar da hanyar sadarwa ta amfani da bayanan SQLite don adana bayanai game da jiharsa. Bayan kowane canji da ya faru a cikin dubawa, an kira aikin fsync(), wanda ya ba da garanti mai kyau na ajiyar bayanan barga. A cikin tsarin fayil na ext3 da aka yi amfani da shi, aikin fsync() an watsar da su zuwa faifai duk shafukan "datti" a cikin tsarin, kuma ba kawai waɗanda ke da alaƙa da fayil ɗin da ya dace ba. Wannan yana nufin danna maɓalli a Firefox zai iya sa a rubuta megabyte na bayanai zuwa faifan maganadisu, wanda zai ɗauki daƙiƙa masu yawa. Maganin matsalar, kamar yadda na fahimta daga gare ta shi abu, shine don matsar da aikin tare da ma'ajin bayanai zuwa ayyuka masu kama da juna. Wannan yana nufin cewa Firefox ta yi amfani da aiwatar da tsauraran buƙatun dagewar ajiya fiye da yadda ake buƙata da gaske, kuma fasalulluka na tsarin fayil na ext3 sun ƙara tsananta wannan matsalar.

Matsala ta biyu ta faru ne a shekara ta 2009. Bayan haka, bayan faduwar tsarin, masu amfani da sabon tsarin fayil na ext4 sun gano cewa yawancin sabbin fayilolin da aka ƙirƙira ba su da tsayi, amma hakan bai faru da tsofaffin fayilolin ext3 ba. A cikin sakin layi na baya, na yi magana game da yadda ext3 ya zubar da bayanai da yawa a kan faifai, wanda ya rage abubuwa da yawa. fsync(). Don inganta halin da ake ciki, ext4 yana watsawa kawai waɗancan shafukan "datti" waɗanda suka dace da takamaiman fayil. Kuma bayanan wasu fayiloli suna kasancewa cikin ƙwaƙwalwar ajiya na dogon lokaci fiye da ext3. Anyi wannan don inganta aikin (ta tsohuwa, bayanan yana tsayawa a cikin wannan yanayin na tsawon daƙiƙa 30, zaku iya saita wannan ta amfani da datti_expire_centisecs; a nan za ku iya samun ƙarin bayani akan wannan). Wannan yana nufin cewa za a iya rasa babban adadin bayanai ba tare da ɓata lokaci ba bayan haɗari. Maganin wannan matsala shine amfani fsync() a cikin aikace-aikacen da ke buƙatar samar da kwanciyar hankali na ajiyar bayanai da kuma kare su kamar yadda zai yiwu daga sakamakon gazawar. Aiki fsync() yana aiki da inganci tare da ext4 fiye da ext3. Lalacewar wannan hanyar ita ce, amfani da shi, kamar da, yana jinkirta wasu ayyuka, kamar shigar da shirye-shirye. Dubi cikakken bayani akan wannan a nan и a nan.

Matsala ta uku dangane da fsync(), ya samo asali a cikin 2018. Sa'an nan, a cikin tsarin aikin PostgreSQL, an gano cewa idan aikin fsync() ya gamu da kuskure, yana yiwa shafuka "datti" alama a matsayin "tsabta". A sakamakon haka, kira masu zuwa fsync() kada ku yi komai da irin waɗannan shafuka. Saboda haka, ana adana shafukan da aka gyara a ƙwaƙwalwar ajiya kuma ba a taɓa rubuta su zuwa faifai ba. Wannan babban bala'i ne, saboda aikace-aikacen zai yi tunanin cewa an rubuta wasu bayanai zuwa faifai, amma a zahiri ba zai kasance ba. Irin wannan gazawar fsync() ne rare, aikace-aikace a irin wannan yanayi ba zai iya yin kusan kome ba don magance matsalar. A kwanakin nan, lokacin da wannan ya faru, PostgreSQL da sauran aikace-aikacen suna faɗuwa. Yana da, a cikin labarin "Shin aikace-aikace na iya farfadowa daga gazawar fsync?", an bincika wannan matsala dalla-dalla. A halin yanzu mafi kyawun maganin wannan matsala shine amfani da Direct I/O tare da tuta O_SYNC ko da tuta O_DSYNC. Tare da wannan tsarin, tsarin zai ba da rahoton kurakuran da ka iya faruwa yayin aiwatar da takamaiman ayyukan rubuta bayanai, amma wannan hanyar tana buƙatar aikace-aikacen don sarrafa masu buffer da kanta. Kara karantawa game da shi a nan и a nan.

Buɗe fayiloli ta amfani da tutocin O_SYNC da O_DSYNC

Bari mu koma ga tattaunawar hanyoyin Linux waɗanda ke ba da ma'ajin bayanai na dindindin. Wato, muna magana ne game da amfani da tuta O_SYNC ko tuta O_DSYNC lokacin buɗe fayiloli ta amfani da kiran tsarin bude(). Tare da wannan hanyar, kowane aikin rubuta bayanai ana yin aiki kamar bayan kowace umarni write() ana ba da tsarin, bi da bi, umarni fsync() и fdatasync(). A Bayanan Bayani na POSIX wannan shi ake kira "Kammala I/O File Integrity Completion" da "Data Integrity Completion". Babban fa'idar wannan hanyar ita ce kiran tsari ɗaya ne kawai ake buƙatar aiwatar da shi don tabbatar da amincin bayanai, ba biyu ba (misali - write() и fdatasync()). Babban rashin lahani na wannan hanyar shine duk ayyukan rubutawa ta amfani da madaidaicin bayanin fayil za a daidaita su, wanda zai iya iyakance ikon tsara lambar aikace-aikacen.

Amfani da Direct I/O tare da tutar O_DIRECT

Kiran tsarin open() yana goyan bayan tuta O_DIRECT, wanda aka ƙera don ketare cache ɗin tsarin aiki, yin ayyukan I / O, yin hulɗa kai tsaye tare da faifai. Wannan, a yawancin lokuta, yana nufin cewa umarnin rubutawa da shirin ya bayar za a fassara shi kai tsaye zuwa umarni da nufin yin aiki tare da faifai. Amma, gaba ɗaya, wannan tsarin ba shine maye gurbin ayyukan ba fsync() ko fdatasync(). Gaskiyar ita ce faifan kanta na iya jinkirta ko cache umarni masu dacewa don rubuta bayanai. Kuma, mafi muni, a wasu lokuta na musamman, ayyukan I / O da aka yi yayin amfani da tuta O_DIRECT, watsa shirye-shirye cikin ayyukan buffered na gargajiya. Hanya mafi sauƙi don magance wannan matsalar ita ce amfani da tuta don buɗe fayiloli O_DSYNC, wanda ke nufin cewa kowane aiki na rubutu zai biyo bayan kira fdatasync().

Ya bayyana cewa tsarin fayil ɗin XFS kwanan nan ya ƙara "hanyar sauri" don O_DIRECT|O_DSYNC- bayanan bayanan. Idan an sake rubuta toshe ta amfani da shi O_DIRECT|O_DSYNC, to, XFS, maimakon zubar da cache, zai aiwatar da umarnin rubuta FUA idan na'urar ta goyi bayansa. Na tabbatar da wannan ta amfani da mai amfani blktrace akan tsarin Linux 5.4/Ubuntu 20.04. Ya kamata wannan hanyar ta zama mafi inganci, tunda tana rubuta mafi ƙarancin adadin bayanai zuwa faifai kuma yana amfani da aiki ɗaya, ba guda biyu ba (rubuta da goge cache). Na sami hanyar haɗi zuwa faci 2018 kernel wanda ke aiwatar da wannan tsarin. Akwai wasu tattaunawa game da amfani da wannan haɓakawa zuwa wasu tsarin fayil, amma kamar yadda na sani, XFS shine kawai tsarin fayil ɗin da ke goyan bayan sa ya zuwa yanzu.

sync_file_range() aiki

Linux yana da tsarin kira sync_file_range(), wanda ke ba ka damar juyar da ɓangaren fayil ɗin zuwa faifai, ba duka fayil ɗin ba. Wannan kiran yana ƙaddamar da ruwa mai kama da juna kuma baya jira ya kammala. Amma dangane da sync_file_range() An ce wannan umarni yana da "haɗari sosai". Ba a ba da shawarar yin amfani da shi ba. Siffofin da hatsarori sync_file_range() an bayyana sosai a ciki wannan abu. Musamman ma, wannan kiran yana da alama yana amfani da RocksDB don sarrafawa lokacin da kernel ke fitar da bayanan "datti" zuwa faifai. Amma a lokaci guda a can, don tabbatar da ingantaccen ajiyar bayanai, ana amfani da shi fdatasync(). A lambar RocksDB yana da wasu sharhi masu ban sha'awa akan wannan batu. Misali, yana kama da kiran sync_file_range() Lokacin amfani da ZFS baya ja da bayanai zuwa faifai. Kwarewa tana gaya mani cewa lambar da ba kasafai ake amfani da ita na iya ƙunsar kwari ba. Don haka, zan ba da shawarar yin amfani da wannan tsarin kiran sai dai idan ya zama dole.

Kiran tsarin don taimakawa tabbatar da dacewar bayanai

Na yanke shawarar cewa akwai hanyoyi guda uku da za a iya amfani da su don aiwatar da ayyukan I/O na dindindin. Duk suna buƙatar kiran aiki fsync() ga directory inda aka ƙirƙiri fayil ɗin. Waɗannan su ne hanyoyin:

  1. Kiran aiki fdatasync() ko fsync() bayan aiki write() (mai kyau don amfani fdatasync()).
  2. Yin aiki tare da bayanin fayil da aka buɗe tare da tuta O_DSYNC ko O_SYNC (mafi kyau - tare da tuta O_DSYNC).
  3. Amfani da umarni pwritev2() da tuta RWF_DSYNC ko RWF_SYNC (zai fi dacewa da tuta RWF_DSYNC).

Bayanan Ayyuka

Ban auna aikin hanyoyin da na bincika ba a hankali. Bambance-bambancen da na lura a cikin saurin aikin su kadan ne. Wannan yana nufin cewa zan iya yin kuskure, kuma a wasu yanayi abu ɗaya na iya nuna sakamako daban-daban. Na farko, zan yi magana game da abin da ya fi shafar aiki, sa'an nan kuma, game da abin da ke rinjayar ƙarancin aiki.

  1. Rubutun bayanan fayil yana da sauri fiye da haɗa bayanai zuwa fayil (ribar aikin na iya zama 2-100%). Haɗa bayanai zuwa fayil yana buƙatar ƙarin canje-canje ga metadata na fayil, koda bayan kiran tsarin fallocate(), amma girman wannan tasirin na iya bambanta. Ina ba da shawarar, don mafi kyawun aiki, don kira fallocate() don ƙaddamar da sararin da ake buƙata. Sa'an nan kuma dole ne a cika wannan fili a fili da sifili kuma a kira shi fsync(). Wannan zai sa a yi wa madaidaitan tubalan da ke cikin tsarin fayil ɗin alama a matsayin “an ware” maimakon “wanda ba a raba”. Wannan yana ba da ƙarami (kimanin 2%) haɓaka aiki. Hakanan, wasu faifai na iya samun aikin toshewa na farko a hankali fiye da wasu. Wannan yana nufin cewa cika sararin samaniya tare da sifilai na iya haifar da ingantaccen aiki (kimanin 100%). Musamman, wannan na iya faruwa tare da faifai. Farashin EBS (wannan bayanan ba na hukuma bane, ba zan iya tabbatar da su ba). Haka ma ajiya. GCP Dindindin Disk (kuma wannan tuni bayanan hukuma ne, an tabbatar da su ta hanyar gwaje-gwaje). Sauran masana sun yi haka luramasu alaka da faifai daban-daban.
  2. Ƙananan kiran tsarin, mafi girman aikin (ribar na iya zama kusan 5%). Yana kama da kira open() da tuta O_DSYNC ko kira pwritev2() da tuta RWF_SYNC sauri kira fdatasync(). Ina tsammanin abin da ake nufi a nan shi ne cewa tare da wannan hanya, gaskiyar cewa ƙananan kira na tsarin dole ne a yi don magance wannan aiki (kira daya maimakon biyu) yana taka rawa. Amma bambancin aikin yana da ƙanƙanta, don haka zaka iya yin watsi da shi cikin sauƙi kuma ka yi amfani da wani abu a cikin aikace-aikacen da ba zai haifar da rikitarwa na basirarsa ba.

Idan kuna sha'awar batun adana bayanai mai dorewa, ga wasu abubuwa masu amfani:

  • Hanyoyin isa ga I/O - bayyani na tushen hanyoyin shigarwa / fitarwa.
  • Tabbatar da bayanai sun isa faifai - labari game da abin da ke faruwa da bayanan akan hanya daga aikace-aikacen zuwa faifai.
  • Yaushe ya kamata ka fsync directory ɗin da ke ƙunshe - amsar tambayar lokacin da ake nema fsync() don kundayen adireshi. A takaice, ya bayyana cewa kana buƙatar yin wannan lokacin ƙirƙirar sabon fayil, kuma dalilin wannan shawarar shine cewa a cikin Linux ana iya samun nassoshi da yawa zuwa fayil iri ɗaya.
  • SQL Server akan Linux: FUA Internals - Anan akwai bayanin yadda ake aiwatar da ma'ajin bayanai na dindindin a cikin SQL Server akan dandamalin Linux. Akwai wasu kwatance masu ban sha'awa tsakanin kiran tsarin Windows da Linux anan. Na kusan tabbata cewa godiya ga wannan kayan ne na koya game da inganta FUA na XFS.

Shin kun taɓa rasa bayanan da kuke tunanin an adana su cikin aminci a faifai?

Ma'ajiyar Bayanai Mai Dorewa da APIs Fayil na Linux

Ma'ajiyar Bayanai Mai Dorewa da APIs Fayil na Linux

source: www.habr.com