Ibi ipamọ data ti o tọ ati Awọn API faili Linux

Lakoko ti o n ṣe iwadii iduroṣinṣin ti ipamọ data ni awọn ọna ṣiṣe awọsanma, Mo pinnu lati ṣe idanwo ara mi lati rii daju pe Mo loye awọn nkan ipilẹ. I bẹrẹ nipasẹ kika NVMe sipesifikesonu Lati le ni oye kini awọn iṣeduro nipa ibi ipamọ data alagbero (iyẹn ni, awọn iṣeduro pe data yoo wa lẹhin ikuna eto) fun wa ni awọn disiki NMVe. Mo ṣe awọn ipinnu akọkọ wọnyi: data gbọdọ jẹ pe o bajẹ lati akoko ti a ti fi aṣẹ lati kọ data titi di akoko ti o ti kọwe si alabọde ipamọ. Sibẹsibẹ, pupọ julọ awọn eto ni idunnu lo awọn ipe eto lati ṣe igbasilẹ data.

Ninu ifiweranṣẹ yii, Mo ṣawari awọn ilana ibi ipamọ ti o tẹpẹlẹ ti a pese nipasẹ awọn API faili Linux. O dabi pe ohun gbogbo yẹ ki o rọrun nibi: eto naa n pe aṣẹ naa write(), ati lẹhin pipaṣẹ yii ti pari, data naa yoo wa ni ipamọ lailewu si disk. Sugbon write() nikan daakọ data ohun elo si kaṣe ekuro ti o wa ni Ramu. Lati fi ipa mu eto lati kọ data si disk, o nilo lati lo diẹ ninu awọn ọna ṣiṣe afikun.

Ibi ipamọ data ti o tọ ati Awọn API faili Linux

Lapapọ, ohun elo yii jẹ akojọpọ awọn akọsilẹ ti o jọmọ ohun ti Mo ti kọ lori koko ti o nifẹ si mi. Ti a ba sọrọ ni ṣoki nipa ohun pataki julọ, o wa ni pe lati ṣeto ibi ipamọ data alagbero o nilo lati lo aṣẹ naa fdatasync() tabi ṣi awọn faili pẹlu asia O_DSYNC. Ti o ba nifẹ si imọ diẹ sii nipa ohun ti o ṣẹlẹ si data lori ọna rẹ lati koodu si disk, wo eyi article.

Awọn ẹya ara ẹrọ ti lilo iṣẹ kikọ ().

Ipe eto write() telẹ ninu awọn bošewa IEEE POSIX bi igbiyanju lati kọ data si olutọpa faili. Lẹhin ti pari aṣeyọri write() Awọn iṣẹ ṣiṣe kika data gbọdọ da pada ni deede awọn baiti ti a ti kọ tẹlẹ, ṣiṣe eyi paapaa ti data ba wọle lati awọn ilana miiran tabi awọn okun (awọn okun)wo o apakan ti o yẹ ti boṣewa POSIX). o ti wa ni, ni apakan lori bi awọn okun ṣe nlo pẹlu awọn iṣẹ ṣiṣe faili deede, akọsilẹ kan wa ti o sọ pe ti awọn okun meji ba pe awọn iṣẹ wọnyi, lẹhinna ipe kọọkan gbọdọ rii boya gbogbo awọn abajade ti a pinnu ti ipe miiran, tabi rara rara. awọn abajade. Eyi nyorisi ipari pe gbogbo awọn iṣẹ I/O faili gbọdọ di titiipa kan lori orisun ti wọn n ṣiṣẹ lori.

Ṣe eyi tumọ si pe iṣẹ naa write() atomiki ni? Lati oju-ọna imọ-ẹrọ, bẹẹni. Awọn iṣẹ ṣiṣe kika data gbọdọ pada boya gbogbo tabi ohunkohun ti ohun ti a kọ pẹlu write(). Ṣugbọn isẹ naa write(), ní ìbámu pẹ̀lú ìlànà, kò fi dandan ní láti parí nípa kíkọ gbogbo ohun tí a ní kí ó kọ sílẹ̀. O gba ọ laaye lati kọ apakan kan ti data naa. Fun apẹẹrẹ, a le ni awọn okun meji kọọkan ti o fi awọn baiti 1024 kun si faili kan ti a ṣalaye nipasẹ oluṣapejuwe faili kanna. Lati oju-ọna ti boṣewa, abajade itẹwọgba yoo jẹ nigbati iṣẹ kikọ kọọkan le ṣafikun ọkan baiti si faili naa. Awọn iṣẹ wọnyi yoo wa ni atomiki, ṣugbọn lẹhin ti wọn ba ti pari, data ti wọn kowe si faili naa yoo dapọ. Nibi fanfa ti o nifẹ pupọ lori koko yii lori Aponsedanu Stack.

fsync () ati fdatasync () awọn iṣẹ

Ọna to rọọrun lati ṣan data si disk ni lati pe iṣẹ naa fsync(). Iṣẹ yii n beere lọwọ ẹrọ ṣiṣe lati gbe gbogbo awọn bulọọki ti a tunṣe lati kaṣe si disk. Eyi pẹlu gbogbo awọn metadata faili (akoko wiwọle, akoko iyipada faili, ati bẹbẹ lọ). Mo gbagbọ pe a ko nilo metadata yii, nitorina ti o ba mọ pe ko ṣe pataki fun ọ, o le lo iṣẹ naa. fdatasync(). awọn Egba Mi O on fdatasync() a sọ pe lakoko iṣẹ ṣiṣe yii, iru iye metadata ti wa ni fipamọ si disk ti o jẹ “pataki fun ṣiṣe deede ti awọn iṣẹ kika data atẹle.” Ati pe eyi ni pato ohun ti ọpọlọpọ awọn ohun elo bikita nipa.

Iṣoro kan ti o le dide nibi ni pe awọn ọna ṣiṣe wọnyi ko ṣe iṣeduro pe faili naa yoo ṣe awari lẹhin ikuna ti o ṣeeṣe. Ni pato, nigba ṣiṣẹda titun faili, o nilo lati pe fsync() fun liana ti o ni o. Bibẹẹkọ, lẹhin ikuna, o le tan pe faili yii ko si. Idi fun eyi ni pe ni UNIX, nitori lilo awọn ọna asopọ lile, faili kan le wa ninu awọn ilana pupọ. Nitorina, nigba pipe fsync() ko si ọna fun faili lati mọ iru data itọsọna yẹ ki o tun fọ si disk (nibi O le ka diẹ sii nipa eyi). O dabi pe eto faili ext4 lagbara laifọwọyi waye fsync() si awọn ilana ti o ni awọn faili ti o baamu, ṣugbọn eyi le ma jẹ ọran pẹlu awọn ọna ṣiṣe faili miiran.

Ilana yii le ṣe ni oriṣiriṣi lori awọn ọna ṣiṣe faili oriṣiriṣi. Mo lo blktrace lati kọ ẹkọ nipa kini awọn iṣẹ disiki ti a lo ninu awọn ọna ṣiṣe faili ext4 ati XFS. Mejeeji gbe awọn aṣẹ kikọ deede si disiki fun awọn akoonu faili mejeeji ati iwe akọọlẹ eto faili, fọ kaṣe naa, ki o jade nipa ṣiṣe FUA kan (Wiwọle Ẹgbẹ Agbara, kikọ data taara si disiki, yiyọ kaṣe) kọ si iwe akọọlẹ naa. O ṣee ṣe ki wọn ṣe eyi lati jẹrisi pe idunadura naa ti waye. Lori awọn awakọ ti ko ṣe atilẹyin FUA, eyi fa awọn ṣiṣan kaṣe meji. Awọn adanwo mi fihan iyẹn fdatasync() kekere kan bit yiyara fsync(). IwUlO blktrace tọkasi wipe fdatasync() nigbagbogbo kọ data kere si disk (ni ext4 fsync() Levin 20 KiB, ati fdatasync() - 16 KiB). Pẹlupẹlu, Mo rii pe XFS jẹ iyara diẹ ju ext4 lọ. Ati nibi pẹlu iranlọwọ blktrace isakoso lati wa jade wipe fdatasync() ṣan data diẹ si disk (4 KiB ni XFS).

Awọn ipo aibikita ti o dide nigba lilo fsync()

Mo ti le ro ti mẹta ambiguous ipo nipa fsync()eyi ti mo pade ni iwa.

Iru ọran akọkọ waye ni ọdun 2008. Lẹhinna wiwo Firefox 3 di didi ti nọmba nla ti awọn faili ba kọ si disk. Iṣoro naa ni pe imuse ti wiwo naa lo aaye data SQLite lati tọju alaye nipa ipo rẹ. Lẹhin iyipada kọọkan ti o waye ni wiwo, a pe iṣẹ naa fsync(), eyi ti o fun awọn iṣeduro ti o dara ti ipamọ data iduroṣinṣin. Ninu eto faili ext3 lẹhinna lo, iṣẹ naa fsync() Da gbogbo awọn oju-iwe “idọti” sinu eto si disk, kii ṣe awọn ti o ni ibatan si faili ti o baamu. Eyi tumọ si pe titẹ bọtini kan ni Firefox le fa awọn megabytes ti data lati kọ si disk oofa, eyiti o le gba awọn aaya pupọ. Ojutu si isoro, bi jina bi mo ti ye lati ti eyi Ohun elo ni lati gbe iṣẹ pẹlu ibi ipamọ data si awọn iṣẹ ṣiṣe isale asynchronous. Eyi tumọ si pe Firefox tẹlẹ ṣe imuse awọn ibeere ibi ipamọ to lagbara diẹ sii ju ti o nilo gaan lọ, ati awọn ẹya ti eto faili ext3 nikan mu iṣoro yii buru si.

Iṣoro keji waye ni ọdun 2009. Lẹhinna, lẹhin jamba eto kan, awọn olumulo ti eto faili ext4 tuntun ti dojuko pẹlu otitọ pe ọpọlọpọ awọn faili tuntun ti a ṣẹda ni gigun odo, ṣugbọn eyi ko ṣẹlẹ pẹlu eto faili ext3 agbalagba. Ninu paragi ti tẹlẹ, Mo ti sọrọ nipa bi ext3 ṣe fọ data pupọ si disk, eyiti o fa fifalẹ awọn nkan lọpọlọpọ. fsync(). Lati mu ipo naa dara, ni ext4 nikan awọn oju-iwe idọti ti o ṣe pataki si faili kan ni a fọ ​​si disk. Ati data lati awọn faili miiran wa ni iranti fun igba pipẹ pupọ ju pẹlu ext3. Eyi ni a ṣe lati mu ilọsiwaju ṣiṣẹ (nipasẹ aiyipada, data duro ni ipo yii fun awọn aaya 30, o le tunto eyi nipa lilo idọti_expire_centisecs; nibi O le wa awọn ohun elo afikun nipa eyi). Eleyi tumo si wipe kan ti o tobi iye ti data le ti wa ni irretrievably sọnu lẹhin kan ikuna. Ojutu si iṣoro yii ni lati lo fsync() ninu awọn ohun elo ti o nilo lati rii daju ibi ipamọ data iduroṣinṣin ati daabobo wọn bi o ti ṣee ṣe lati awọn abajade ti awọn ikuna. Išẹ fsync() ṣiṣẹ daradara siwaju sii nigba lilo ext4 ju nigba lilo ext3. Aila-nfani ti ọna yii ni pe lilo rẹ, bi tẹlẹ, fa fifalẹ ipaniyan ti diẹ ninu awọn iṣẹ, bii fifi awọn eto sori ẹrọ. Wo alaye nipa eyi nibi и nibi.

Awọn kẹta isoro nipa fsync(), ti ipilẹṣẹ ni ọdun 2018. Lẹhinna, laarin ilana ti ise agbese PostgreSQL, a rii pe ti iṣẹ naa ba fsync() pade aṣiṣe, o samisi awọn oju-iwe "idọti" bi "mimọ". Bi abajade, awọn ipe atẹle fsync() Wọn ko ṣe ohunkohun pẹlu iru awọn oju-iwe bẹẹ. Nitori eyi, awọn oju-iwe ti a ṣe atunṣe ti wa ni ipamọ sinu iranti ati pe a ko kọ si disk rara. Eyi jẹ ajalu gidi, nitori ohun elo naa yoo ro pe diẹ ninu awọn data ti kọ si disk, ṣugbọn ni otitọ kii yoo jẹ. Iru ikuna fsync() jẹ toje, ohun elo ni iru awọn ipo ko le ṣe ohunkohun lati koju iṣoro naa. Awọn ọjọ wọnyi, nigbati eyi ba ṣẹlẹ, PostgreSQL ati awọn ohun elo miiran ṣubu. o ti wa ni, ninu ohun elo "Ṣe Awọn ohun elo le Bọsipọ lati Awọn Ikuna fsync?", A ṣawari iṣoro yii ni awọn alaye. Lọwọlọwọ ojutu ti o dara julọ si iṣoro yii ni lati lo Taara I/O pẹlu asia O_SYNC tabi pẹlu asia O_DSYNC. Pẹlu ọna yii, eto naa yoo jabo awọn aṣiṣe ti o le waye lakoko awọn iṣẹ kikọ kan pato, ṣugbọn ọna yii nilo ohun elo lati ṣakoso awọn buffer funrararẹ. Ka diẹ sii nipa eyi nibi и nibi.

Ṣiṣii awọn faili ni lilo awọn asia O_SYNC ati O_DSYNC

Jẹ ki a pada si ijiroro ti awọn ẹrọ Linux ti o pese ibi ipamọ data iduroṣinṣin. Eyun, a n sọrọ nipa lilo asia O_SYNC tabi asia O_DSYNC nigba ṣiṣi awọn faili nipa lilo ipe eto ṣii(). Pẹlu ọna yii, iṣẹ kikọ data kọọkan ni a ṣe bi ẹnipe lẹhin aṣẹ kọọkan write() eto ni a fun ni aṣẹ ni ibamu fsync() и fdatasync(). awọn POSIX ni pato eyi ni a npe ni "Imuṣiṣẹpọ I/O Faili Iṣeduro Iṣeduro Iṣeduro" ati "Ipari Iṣeduro Data". Anfani akọkọ ti ọna yii ni pe lati rii daju iduroṣinṣin data, o nilo lati ṣe ipe eto kan, ju meji lọ (fun apẹẹrẹ - write() и fdatasync()). Aila-nfani akọkọ ti ọna yii ni pe gbogbo awọn kikọ nipa lilo oluṣapejuwe faili ti o baamu yoo jẹ mimuuṣiṣẹpọ, eyiti o le ṣe idinwo agbara lati ṣeto koodu ohun elo naa.

Lilo Direct I/O pẹlu O_DIRECT asia

Ipe eto open() atilẹyin asia O_DIRECT, eyi ti a ṣe lati fori kaṣe ẹrọ ṣiṣe lati ṣe awọn iṣẹ I / O nipasẹ sisọ taara pẹlu disk naa. Eyi, ni ọpọlọpọ awọn ọran, tumọ si pe awọn aṣẹ kikọ ti o funni nipasẹ eto naa yoo tumọ taara si awọn aṣẹ ti o pinnu lati ṣiṣẹ pẹlu disiki naa. Ṣugbọn, ni gbogbogbo, ẹrọ yii kii ṣe iyipada fun awọn iṣẹ fsync() tabi fdatasync(). Otitọ ni pe disk funrararẹ le da duro tabi kaṣe ibamu data kikọ ase. Ati pe, lati jẹ ki ọrọ buru si, ni awọn ọran pataki awọn iṣẹ I/O ṣe nigba lilo asia O_DIRECT, igbohunsafefe sinu ibile buffered mosi. Ọna to rọọrun lati yanju iṣoro yii ni lati lo asia lati ṣii awọn faili O_DSYNC, eyi ti yoo tumọ si pe iṣẹ kikọ kọọkan yoo jẹ atẹle nipasẹ ipe kan fdatasync().

O wa ni jade wipe XFS faili eto ti laipe fi kun a "sare ona" fun O_DIRECT|O_DSYNC- gbigbasilẹ data. Ti a ba tun bulọki kọ nipa lilo O_DIRECT|O_DSYNC, lẹhinna XFS, dipo fifin kaṣe, yoo ṣiṣẹ aṣẹ kikọ FUA ti ẹrọ naa ba ṣe atilẹyin. Mo jẹrisi eyi nipa lilo ohun elo naa blktrace lori eto Linux 5.4/Ubuntu 20.04. Ọna yii yẹ ki o munadoko diẹ sii, niwon nigba lilo, iye data ti o kere ju ni a kọ si disk ati pe a lo iṣẹ kan, ju meji lọ (kikọ ati fifọ kaṣe naa). Mo ti ri ọna asopọ kan si alemo Ekuro 2018, eyiti o ṣe imuse ẹrọ yii. Ifọrọwọrọ kan wa nibẹ nipa lilo iṣapeye yii si awọn ọna ṣiṣe faili miiran, ṣugbọn bi Mo ti mọ, XFS nikan ni eto faili ti o ṣe atilẹyin eyi titi di isisiyi.

sync_file_range () iṣẹ

Lainos ni ipe eto kan sync_file_range (), eyiti o fun ọ laaye lati fọ apakan nikan ti faili si disk, ju gbogbo faili lọ. Ipe yii ṣe pilẹṣẹ danu data asynchronous ko si duro fun lati pari. Ṣugbọn ninu iwe-ẹri naa sync_file_range() a sọ pe ẹgbẹ naa jẹ "ewu pupọ". Ko ṣe iṣeduro lati lo. Awọn ẹya ara ẹrọ ati awọn ewu sync_file_range() gan daradara apejuwe ninu eyi ohun elo. Ni pataki, ipe yii yoo han lati lo RocksDB lati ṣakoso nigbati kernel ba fọ data idọti si disk. Ṣugbọn ni akoko kanna, lati rii daju ibi ipamọ data iduroṣinṣin, o tun lo fdatasync(). awọn koodu RocksDB ni diẹ ninu awọn asọye ti o nifẹ si lori koko yii. Fun apẹẹrẹ, o han pe ipe naa sync_file_range() Nigbati o ba nlo ZFS, ko da data ṣan si disk. Iriri sọ fun mi pe koodu ti o ṣọwọn lo ṣee ṣe lati ni awọn idun ninu. Nitorinaa, Emi yoo ni imọran lodi si lilo ipe eto yii ayafi ti o jẹ dandan.

Awọn ipe eto ti o ṣe iranlọwọ rii daju itẹramọ data

Mo ti wa si ipari pe awọn ọna mẹta lo wa ti o le ṣee lo lati ṣe awọn iṣẹ I/O ti o rii daju itẹramọ data. Gbogbo wọn nilo ipe iṣẹ kan fsync() fun awọn liana ninu eyi ti awọn faili ti a da. Awọn wọnyi ni awọn ọna:

  1. Npe iṣẹ kan fdatasync() tabi fsync() lẹhin iṣẹ write() (o dara julọ lati lo fdatasync()).
  2. Nṣiṣẹ pẹlu oluṣapejuwe faili ti o ṣii pẹlu asia kan O_DSYNC tabi O_SYNC (dara julọ - pẹlu asia kan O_DSYNC).
  3. Lilo aṣẹ pwritev2() pelu asia RWF_DSYNC tabi RWF_SYNC (Pẹlupẹlu pẹlu asia kan RWF_DSYNC).

Awọn akọsilẹ iṣẹ

Emi ko farabalẹ wọn iṣẹ ṣiṣe ti awọn ọna oriṣiriṣi ti Mo ti ṣe ayẹwo. Awọn iyatọ ti mo ṣe akiyesi ni iyara ti iṣẹ wọn kere pupọ. Eyi tumọ si pe MO le jẹ aṣiṣe, ati pe labẹ awọn ipo oriṣiriṣi ohun kanna le ṣe awọn abajade oriṣiriṣi. Ni akọkọ, Emi yoo sọrọ nipa ohun ti yoo ni ipa lori iṣẹ diẹ sii, ati lẹhinna kini yoo ni ipa lori iṣẹ ṣiṣe kere si.

  1. Akọkọ data faili yiyara ju fifi data si faili kan (anfani iṣẹ le jẹ 2-100%). Fifi data si faili nilo afikun awọn ayipada si metadata faili naa, paapaa lẹhin ipe eto kan fallocate(), ṣugbọn titobi ipa yii le yatọ. Mo ṣeduro, fun iṣẹ ṣiṣe to dara julọ, lati pe fallocate() lati ṣaju-sọtọ aaye ti a beere. Lẹhinna aaye yii gbọdọ wa ni kikun pẹlu awọn odo ati pe fsync(). Eyi yoo rii daju pe awọn bulọọki ti o baamu ninu eto faili jẹ samisi bi “ipinpin” dipo “aiṣe-pin”. Eyi funni ni ilọsiwaju iṣẹ ṣiṣe kekere (nipa 2%). Ni afikun, diẹ ninu awọn disiki le ni iwọle akọkọ ti o lọra si bulọki ju awọn miiran lọ. Eyi tumọ si pe kikun aaye pẹlu awọn odo le ja si ilọsiwaju pataki (nipa 100%) ninu iṣẹ. Ni pato, eyi le ṣẹlẹ pẹlu awọn disiki Aws EBS (Eyi jẹ data laigba aṣẹ, Emi ko le jẹrisi rẹ). Kanna n lọ fun ibi ipamọ Disk Jubẹẹlo GCP (ati pe eyi jẹ alaye osise tẹlẹ, timo nipasẹ awọn idanwo). Awọn amoye miiran ti ṣe kanna akiyesi, jẹmọ si orisirisi awọn disks.
  2. Awọn ipe eto ti o dinku, iṣẹ ṣiṣe ti o ga julọ (ere le jẹ nipa 5%). O dabi ipenija open() pelu asia O_DSYNC tabi ipe pwritev2() pelu asia RWF_SYNC yiyara ju ipe kan lọ fdatasync(). Mo fura pe aaye nibi ni pe ọna yii ṣe ipa kan ni otitọ pe awọn ipe eto diẹ ni lati ṣe lati yanju iṣoro kanna (ipe kan dipo meji). Ṣugbọn iyatọ ninu iṣẹ jẹ kekere pupọ, nitorinaa o le ni rọọrun foju rẹ ki o lo ohunkan ninu ohun elo rẹ ti kii yoo ṣe idiju ọgbọn rẹ.

Ti o ba nifẹ si koko-ọrọ ti ipamọ data alagbero, eyi ni diẹ ninu awọn ohun elo to wulo:

  • Awọn ọna Wiwọle I/O - Akopọ ti awọn ipilẹ ti awọn ọna ṣiṣe titẹ sii / o wu.
  • Aridaju data Gigun disk - itan kan nipa ohun ti o ṣẹlẹ si data lori ọna lati ohun elo si disiki naa.
  • Nigbawo ni o yẹ ki o fsync ti ilana ti o ni ninu - idahun si ibeere ti nigbati lati lo fsync() fun awọn ilana. Lati fi eyi sinu kukuru, o wa ni pe o nilo lati ṣe eyi nigbati o ba ṣẹda faili titun kan, ati pe idi fun iṣeduro yii ni pe ni Lainos o le jẹ ọpọlọpọ awọn itọkasi si faili kanna.
  • SQL Server lori Lainos: FUA Internals - eyi ni apejuwe bi ibi ipamọ data ti o tẹpẹlẹ ṣe ṣe imuse ni SQL Server lori pẹpẹ Linux. Awọn afiwera ti o nifẹ si wa laarin awọn ipe eto Windows ati Lainos nibi. Mo ni idaniloju pe o jẹ ọpẹ si ohun elo yii ti Mo kọ ẹkọ nipa iṣapeye FUA ti XFS.

Njẹ o ti padanu data ti o ro pe o ti fipamọ ni aabo lori disk kan?

Ibi ipamọ data ti o tọ ati Awọn API faili Linux

Ibi ipamọ data ti o tọ ati Awọn API faili Linux

orisun: www.habr.com