Нигоҳдории устувори маълумот ва API-ҳои файли Linux

Ҳангоми таҳқиқи устувории нигоҳдории маълумот дар системаҳои абрӣ, ман қарор додам, ки худро санҷам, то боварӣ ҳосил кунам, ки чизҳои асосиро фаҳмидам. И бо хондани мушаххасоти NVMe оғоз ёфт то бифаҳмем, ки чӣ гуна кафолатҳо дар бораи нигоҳдории устувори додаҳо (яъне кафолат медиҳанд, ки маълумот пас аз шикасти система дастрас хоҳад шуд) ба мо дискҳои NMVe медиҳад. Ман чунин хулосаҳои асосиро баровардам: маълумот бояд аз лаҳзаи дода шудани фармони навиштани маълумот то лаҳзаи навиштани он ба муҳити нигоҳдорӣ вайроншуда ҳисобида шавад. Бо вуҷуди ин, аксари барномаҳо барои сабти маълумот зангҳои системаро бо хушнудӣ истифода мебаранд.

Дар ин паём, ман механизмҳои нигаҳдории доимиро, ки аз ҷониби API-ҳои файли Linux пешниҳод шудаанд, меомӯзам. Чунин ба назар мерасад, ки дар ин ҷо ҳама чиз бояд оддӣ бошад: барнома фармонро даъват мекунад write(), ва пас аз иҷрои ин фармон, маълумот дар диск бехатар захира карда мешавад. Аммо write() танҳо маълумоти барномаро ба кэши ядрои дар RAM ҷойгиршуда нусхабардорӣ мекунад. Барои маҷбур кардани система ба навиштани маълумот ба диск, шумо бояд якчанд механизмҳои иловагиро истифода баред.

Нигоҳдории устувори маълумот ва API-ҳои файли Linux

Умуман, ин мавод маҷмӯаи ёддоштҳоест, ки ба он чизе ки ман дар мавзӯи мароқовар омӯхтаам. Агар мо дар бораи чизи аз ҳама муҳим хеле мухтасар сухан ронем, маълум мешавад, ки барои ташкили нигоҳдории устувори маълумот шумо бояд фармонро истифода баред. fdatasync() ё файлҳоро бо парчам кушоед O_DSYNC. Агар шумо ба гирифтани маълумоти бештар дар бораи он, ки бо маълумот дар роҳи аз код ба диск чӣ рӯй медиҳад, таваҷҷӯҳ дошта бошед, ба он назар андозед ин мақола.

Хусусиятҳои истифодаи функсияи write()

Зангҳои системавӣ write() дар стандарт муайян карда шудааст IEEE POSIX ҳамчун кӯшиши навиштани маълумот ба тавсифкунандаи файл. Пас аз анҷоми бомуваффақият write() Амалиётҳои хондани маълумот бояд маҳз байтҳоеро, ки қаблан навишта шуда буданд, баргардонанд, ин корро ҳатто агар ба маълумот аз дигар равандҳо ё риштаҳо дастрас бошад (инак фасли дахлдори стандарти POSIX). Ин аст,, дар бахш дар бораи он ки чӣ тавр риштаҳо бо амалиёти муқаррарии файл мутақобила мекунанд, ёддоште мавҷуд аст, ки агар ду ришта ҳар кадом ин функсияҳоро даъват кунад, пас ҳар як занг бояд ҳама оқибатҳои таъиншудаи занги дигарро бубинад, ё тамоман. оқибатҳои. Ин ба хулосае оварда мерасонад, ки ҳамаи амалиётҳои воридотӣ/базаркунии файл бояд дар захирае, ки дар онҳо кор мекунанд, қулф дошта бошанд.

Оё ин маънои онро дорад, ки амалиёт write() атом аст? Аз чихати техникй, бале. Амалиётҳои хондани маълумот бояд ҳама чизеро, ки бо он навишта шудааст, баргардонад write(). Аммо амалиёт write(), тибқи стандарт, ҳатман бояд бо навиштани ҳама чизе, ки аз он навишта шудааст, анҷом дода шавад. Ба вай иҷозат дода мешавад, ки танҳо як қисми маълумотро нависад. Масалан, мо метавонем ду ришта дошта бошем, ки ҳар кадоми онҳо 1024 байтро ба файле, ки аз ҷониби як дескриптори файл тавсиф шудааст, замима мекунанд. Аз нуқтаи назари стандарт, натиҷаи қобили қабул хоҳад буд, вақте ки ҳар як амалиёти навиштан метавонад ба файл танҳо як байт илова кунад. Ин амалиётҳо атомӣ боқӣ мемонанд, аммо пас аз анҷоми онҳо, маълумоте, ки онҳо ба файл навиштаанд, омехта мешавад. дар ин ҷо муҳокимаи хеле ҷолиб дар бораи ин мавзӯъ дар Stack Overflow.

Функсияҳои fsync () ва fdatasync ().

Роҳи осонтарини тоза кардани маълумот ба диск ин даъват кардани функсия мебошад fsync(). Ин функсия аз системаи оператсионӣ хоҳиш мекунад, ки ҳамаи блокҳои тағирёфтаро аз кэш ба диск интиқол диҳад. Ин ҳама метамаълумоти файлро дар бар мегирад (вақти дастрасӣ, вақти тағир додани файл ва ғайра). Ман боварӣ дорам, ки ин метадата хеле кам лозим аст, бинобар ин, агар шумо донед, ки ин барои шумо муҳим нест, шумо метавонед ин функсияро истифода баред fdatasync(). Дар Кӯмак ба fdatasync() Гуфта мешавад, ки дар ҷараёни кори ин функсия чунин миқдори метамаълумотҳо дар диск захира карда мешаванд, ки "барои иҷрои дурусти амалиёти хондани маълумотҳои зерин заруранд". Ва ин маҳз он чизест, ки аксари барномаҳо дар бораи он ғамхорӣ мекунанд.

Як мушкилоте, ки дар ин ҷо пайдо шуда метавонад, ин аст, ки ин механизмҳо кафолат намедиҳанд, ки файл пас аз нокомии эҳтимолӣ ошкор мешавад. Аз ҷумла, ҳангоми сохтани файли нав, шумо бояд занг занед fsync() барои директорияе, ки онро дарбар мегирад. Дар акси ҳол, пас аз нокомӣ, маълум мешавад, ки ин файл вуҷуд надорад. Сабаби ин дар он аст, ки дар UNIX аз сабаби истифодаи истинодҳои сахт, файл метавонад дар якчанд директория мавҷуд бошад. Бинобар ин, хангоми занг задан fsync() Ягон роҳе нест, ки файл бидонад, ки кадом маълумоти директория инчунин бояд ба диск тоза карда шавад (дар ин ҷо Шумо метавонед дар ин бора бештар хонед). Чунин ба назар мерасад, ки системаи файлии ext4 қодир аст худкор истифода бурдан fsync() ба директорияҳои дорои файлҳои мувофиқ, аммо ин метавонад бо дигар системаҳои файлӣ набошад.

Ин механизм метавонад дар системаҳои файлии гуногун ба таври гуногун амалӣ карда шавад. истифода кардам blktrace Барои фаҳмидани он, ки кадом амалиётҳои диск дар системаҳои файлии ext4 ва XFS истифода мешаванд. Ҳарду фармонҳои муқаррарии навиштанро ба диск ҳам барои мундариҷаи файл ва ҳам маҷаллаи системаи файлӣ медиҳанд, кэшро тоза мекунанд ва тавассути иҷрои FUA (Force Unit Access, навиштани маълумот ба диск мустақиман, гузариш аз кэш) ба маҷалла нависед. Эҳтимол онҳо ин корро барои тасдиқи он анҷом медиҳанд, ки муомилот сурат гирифтааст. Дар дискҳое, ки FUA-ро дастгирӣ намекунанд, ин боиси ду тозакунии кэш мегардад. Тачрибахои ман инро нишон доданд fdatasync() каме тезтар fsync(). Утилита blktrace нишон медихад fdatasync() одатан ба диск камтар маълумот менависад (дар ext4 fsync() менависад 20 КБ, ва fdatasync() - 16 КБ). Инчунин, ман фаҳмидам, ки XFS нисбат ба ext4 каме тезтар аст. Ва дар ин ҷо бо кӯмак blktrace муяссар шуд, ки онро фахмад fdatasync() кам маълумотро ба диск мерезад (4 киб дар XFS).

Ҳолатҳои номуайяне, ки ҳангоми истифодаи fsync() ба вуҷуд меоянд

Ман метавонам дар бораи се ҳолати номуайян дар бораи он фикр кунам fsync()ки дар амал дучор шудам.

Аввалин чунин ҳодиса соли 2008 рух дода буд. Пас аз он интерфейси Firefox 3 ях мекунад, агар шумораи зиёди файлҳо ба диск навишта шуда бошанд. Мушкилот дар он буд, ки татбиқи интерфейс аз пойгоҳи додаҳои SQLite барои нигоҳ доштани маълумот дар бораи ҳолати он истифода мешуд. Пас аз ҳар як тағирот, ки дар интерфейс рух дод, функсия даъват карда шуд fsync(), ки кафолати хуби нигоҳдории устувори маълумот дод. Дар системаи файлии ext3, он гоҳ функсия истифода мешавад fsync() ҳамаи саҳифаҳои "ифлос"-и системаро ба диск партофтанд, на танҳо саҳифаҳое, ки ба файли мувофиқ алоқаманд буданд. Ин маънои онро дошт, ки пахш кардани тугма дар Firefox метавонад мегабайтҳои маълумотро ба диски магнитӣ навишт, ки сонияҳои зиёдеро дарбар мегирад. Ҳалли мушкилот, то ҷое ки ман аз он фаҳмидам ин мавод барои интиқол додани кор бо пойгоҳи додаҳо ба вазифаҳои заминаи асинхронӣ буд. Ин маънои онро дорад, ки Firefox қаблан талаботҳои сахттари нигаҳдории нигоҳдорӣ нисбат ба воқеан лозим буд, ва хусусиятҳои системаи файлии ext3 ин мушкилотро боз ҳам шадидтар карданд.

Мушкилоти дуюм дар соли 2009 рух дод. Сипас, пас аз садамаи система, корбарони системаи нави файлии ext4 бо он дучор шуданд, ки бисёре аз файлҳои навтаъсис сифр дарозӣ доштанд, аммо ин бо системаи файлии кӯҳнаи ext3 рӯй надодааст. Дар параграфи қаблӣ, ман дар бораи он сӯҳбат кардам, ки чӣ тавр ext3 ба диск маълумотҳои аз ҳад зиёд рехтааст, ки ин корро хеле суст мекунад. fsync(). Барои беҳтар кардани вазъият, дар ext4 танҳо он саҳифаҳои ифлос, ки ба файли мушаххас мувофиқанд, ба диск тоза карда мешаванд. Ва маълумот аз файлҳои дигар назар ба ext3 дар хотира муддати хеле дароз боқӣ мемонад. Ин барои беҳтар кардани кор анҷом дода шудааст (бо нобаёнӣ, маълумот дар ин ҳолат 30 сония боқӣ мемонад, шумо метавонед онро бо истифода аз он танзим кунед. dirty_expire_centisecs; дар ин ҷо Шумо метавонед дар ин бора маводи иловагиро пайдо кунед). Ин маънои онро дорад, ки миқдори зиёди маълумот метавонад пас аз нокомӣ бебозгашт гум шавад. Халли ин масъала истифода бурдан аст fsync() дар барномаҳое, ки бояд нигоҳдории устувори маълумотро таъмин кунанд ва онҳоро то ҳадди имкон аз оқибатҳои нокомиҳо муҳофизат кунанд. Функсия fsync() ҳангоми истифодаи ext4 назар ба истифодаи ext3 хеле самараноктар кор мекунад. Камбудии ин равиш дар он аст, ки истифодабарии он мисли пештара иҷрои баъзе амалиётҳоро, масалан насб кардани барномаҳоро суст мекунад. Тафсилотро дар ин бора бубинед дар ин ҷо и дар ин ҷо.

Масъалаи сеюм вобаста ба fsync(), дар соли 2018 таъсис ёфтааст. Сипас, дар доираи лоиҳаи PostgreSQL маълум шуд, ки агар функсия fsync() ба хато дучор мешавад, он саҳифаҳои "ифлос" -ро ҳамчун "тоза" қайд мекунад. Дар натича зангхои зерин fsync() Онҳо бо чунин саҳифаҳо коре намекунанд. Аз ин сабаб, саҳифаҳои тағирёфта дар хотира нигоҳ дошта мешаванд ва ҳеҷ гоҳ ба диск навишта намешаванд. Ин як фалокати воқеӣ аст, зеро барнома фикр мекунад, ки баъзе маълумот ба диск навишта шудааст, аммо дар асл ин тавр нахоҳад буд. Чунин нобарориҳо fsync() каманд, барнома дар чунин ҳолатҳо барои мубориза бо мушкилот қариб ҳеҷ кор карда наметавонад. Дар ин рӯзҳо, вақте ки ин рӯй медиҳад, PostgreSQL ва дигар барномаҳо ба кор медароянд. Ин аст,, дар маводи "Оё барномаҳо аз хатогиҳои fsync барқарор мешаванд?", ин мушкилот ба таври муфассал омӯхта шудааст. Дар айни замон беҳтарин роҳи ҳалли ин мушкилот истифодаи мустақими I/O бо парчам мебошад O_SYNC ё бо парчам O_DSYNC. Бо ин равиш, система хатогиҳоеро, ки дар ҷараёни амалиёти мушаххаси навиштан рух дода метавонанд, гузориш медиҳад, аммо ин равиш аз барнома идора кардани буферҳо талаб мекунад. Дар ин бора бештар хонед дар ин ҷо и дар ин ҷо.

Кушодани файлҳо бо истифода аз парчамҳои O_SYNC ва O_DSYNC

Биёед ба муҳокимаи механизмҳои Linux, ки нигоҳдории устувори маълумотро таъмин мекунанд, баргардем. Махз, сухан дар бораи истифодаи парчам меравад O_SYNC ё парчам O_DSYNC ҳангоми кушодани файлҳо бо истифода аз занги система кушодан(). Бо ин равиш, ҳар як амалиёти навиштани маълумот гӯё пас аз ҳар як фармон иҷро карда мешавад write() ба система мувофики фармонхо дода мешавад fsync() и fdatasync(). Дар Мушаххасоти POSIX ин "Анҷоми якпорчагии файли синхронизатсияшудаи вуруд/чор" ва "анҷоми тамомияти маълумот" номида мешавад. Бартарии асосии ин равиш дар он аст, ки барои таъмини тамомияти додаҳо, шумо бояд танҳо як занги системавӣ кунед, на ду (масалан - write() и fdatasync()). Камбудии асосии ин равиш дар он аст, ки ҳама навиштаҷот бо истифода аз дескриптори файли мувофиқ ҳамоҳанг карда мешавад, ки метавонад қобилияти сохтори коди барномаро маҳдуд кунад.

Истифодаи мустақими I/O бо парчами O_DIRECT

Зангҳои системавӣ open() байракро дастгирй мекунад O_DIRECT, ки барои гузаштан аз кэши системаи оператсионӣ барои иҷрои амалиёти воридотӣ / баромад тавассути мутақобилаи мустақим бо диск пешбинӣ шудааст. Ин, дар бисёр мавридҳо, маънои онро дорад, ки фармонҳои навиштани аз ҷониби барнома додашуда мустақиман ба фармонҳое, ки барои кор бо диск нигаронида шудаанд, тарҷума карда мешаванд. Аммо, дар маҷмӯъ, ин механизм иваз кардани вазифаҳо нест fsync() ё fdatasync(). Гап дар сари он аст, ки худи диск метавонад таъхир ё кэш фармонҳои мувофиқи навиштани маълумот. Ва бадтар аз ин, дар баъзе ҳолатҳои махсус амалиёти I/O ҳангоми истифодаи парчам анҷом дода мешавад O_DIRECT, пахш кардан ба амалиёти анъанавии буферӣ. Роҳи осонтарини ҳалли ин мушкилот истифодаи парчам барои кушодани файлҳо мебошад O_DSYNC, ки ин маънои онро дорад, ки ҳар як амалиёти навиштан бо занг пайгирӣ карда мешавад fdatasync().

Маълум шуд, ки системаи файлии XFS ба наздикӣ "роҳи зуд" барои O_DIRECT|O_DSYNC- сабти маълумот. Агар блок бо истифода аз нав навишта шавад O_DIRECT|O_DSYNC, пас XFS ба ҷои тоза кардани кэш, агар дастгоҳ онро дастгирӣ кунад, фармони навиштани FUA-ро иҷро мекунад. Ман инро бо истифода аз утилита тасдиқ кардам blktrace дар системаи Linux 5.4/Ubuntu 20.04. Ин равиш бояд самараноктар бошад, зеро ҳангоми истифода ба диск миқдори ками маълумот навишта мешавад ва як амалиёт истифода мешавад, на ду (навиштан ва тоза кардани кэш). Ман пайвандеро пайдо кардам часпондан ядрои 2018, ки ин механизмро амалӣ мекунад. Дар бораи татбиқи ин оптимизатсия дар дигар системаҳои файлӣ баҳс вуҷуд дорад, аммо то ҷое ки ман медонам, XFS ягона системаи файлист, ки то ҳол инро дастгирӣ мекунад.

функсияи sync_file_range().

Linux занги система дорад sync_file_range(), ки ба шумо имкон медиҳад, ки танҳо як қисми файлро ба диск тоза кунед, на тамоми файл. Ин занг тозакунии асинхронии маълумотро оғоз мекунад ва мунтазири анҷоми он нест. Аммо дар шаҳодатнома sync_file_range() гуфта мешавад, ки команда «хеле хавфнок» аст. Истифодаи он тавсия дода намешавад. Хусусиятҳо ва хатарҳо sync_file_range() хеле хуб тасвир шудааст ин материал. Махсусан, ин занг ба назар мерасад, ки RocksDB-ро барои назорат кардани вақте ки ядро ​​маълумоти ифлосро ба диск тоза мекунад, истифода мебарад. Аммо дар айни замон, барои таъмини нигоҳдории устувори маълумот, он низ истифода мешавад fdatasync(). Дар рамз RocksDB дар ин мавзӯъ шарҳҳои ҷолиб дорад. Масалан, чунин ба назар мерасад, ки занг sync_file_range() Ҳангоми истифодаи ZFS, он маълумотро ба диск тоза намекунад. Таҷриба ба ман мегӯяд, ки рамзи кам истифодашаванда эҳтимол дорад хатогиҳо дошта бошад. Аз ин рӯ, ман маслиҳат медиҳам, ки ин занги системаро дар ҳолати зарурӣ истифода набаред.

Зангҳои системавӣ, ки барои таъмини устувории маълумот кӯмак мекунанд

Ман ба хулосае омадам, ки се равиш вуҷуд дорад, ки онҳоро барои иҷрои амалиёти вуруд/чор истифода бурдан мумкин аст, ки устувории маълумотро таъмин мекунанд. Ҳамаи онҳо занги функсияро талаб мекунанд fsync() барои директорияе, ки дар он файл сохта шудааст. Инҳоянд равишҳо:

  1. Даъвати функсия fdatasync() ё fsync() пас аз функсия write() (истифода бурдан беҳтар аст fdatasync()).
  2. Кор бо дескриптори файл, ки бо парчам кушода мешавад O_DSYNC ё O_SYNC (беҳтараш - бо парчам O_DSYNC).
  3. Истифодаи фармон pwritev2() бо байрак RWF_DSYNC ё RWF_SYNC (бењтараш бо парчам RWF_DSYNC).

Қайдҳои иҷроиш

Ман кори механизмхои гуногуни тафтишкардаамро бодиккат чен накардаам. Фарқиятҳое, ки ман дар суръати кори онҳо мушоҳида кардам, хеле каманд. Ин маънои онро дорад, ки ман хато карда метавонам ва дар шароити гуногун як чиз метавонад натиҷаҳои гуногун диҳад. Аввалан, ман дар бораи он сухан хоҳам гуфт, ки чӣ ба кор бештар таъсир мерасонад ва баъд ба он чӣ камтар таъсир мерасонад.

  1. Навиштани маълумоти файл нисбат ба илова кардани маълумот ба файл тезтар аст (фоидаи иҷроиш метавонад 2-100% бошад). Илова кардани маълумот ба файл ҳатто пас аз занги система тағироти иловагиро ба метамаълумоти файл талаб мекунад fallocate(), аммо андозаи ин таъсир метавонад гуногун бошад. Ман тавсия медиҳам, ки барои иҷрои беҳтарин занг занед fallocate() ки чои заруриро пешакй чудо кунанд. Пас ин фосила бояд ба таври возеҳ бо сифрҳо пур карда шавад ва даъват карда шавад fsync(). Ин кафолат медиҳад, ки блокҳои мувофиқ дар системаи файлӣ ҳамчун "тақсимшуда" ба ҷои "тақсимнашуда" қайд карда мешаванд. Ин як беҳбудии каме (тақрибан 2%) медиҳад. Илова бар ин, баъзе дискҳо метавонанд дастрасии аввал ба блок нисбат ба дигарон сусттар бошанд. Ин маънои онро дорад, ки пур кардани фазо бо сифрҳо метавонад ба беҳбудии назаррас (тақрибан 100%) дар кор оварда расонад. Махсусан, ин метавонад бо дискҳо рӯй диҳад AWS EBS (ин маълумоти ғайрирасмӣ аст, ман онро тасдиқ карда натавонистам). Ҳамин чиз барои нигоҳдорӣ меравад Диски доимии GCP (ва ин аллакай маълумоти расмӣ аст, ки бо санҷишҳо тасдиқ карда шудааст). Мутахассисони дигар низ ҳамин тавр кардаанд мушоҳидаҳо, вобаста ба дискҳои гуногун.
  2. Чӣ қадаре ки зангҳои система камтар бошад, ҳамон қадар кор баландтар мешавад (фоида метавонад тақрибан 5% бошад). Ба назар душворӣ ба назар мерасад open() бо байрак O_DSYNC ё занг занед pwritev2() бо байрак RWF_SYNC тезтар аз занг fdatasync(). Ман гумон мекунам, ки нуқтаи ин ҷо дар он аст, ки ин равиш дар он нақш мебозад, ки барои ҳалли як мушкилот (як занг ба ҷои ду) камтар зангҳои система анҷом дода шаванд. Аммо фарқият дар иҷроиш хеле ночиз аст, бинобар ин шумо метавонед онро комилан нодида гиред ва дар барнома чизеро истифода баред, ки мантиқи онро мушкил накунад.

Агар шумо ба мавзӯи нигоҳдории устувори маълумот таваҷҷӯҳ дошта бошед, инҳоянд чанд маводи муфид:

  • Усулҳои дастрасии вуруд / баромад — шарҳи асосҳои механизмҳои воридотӣ.
  • Боварӣ ҳосил кунед, ки маълумот ба диск мерасад — хикоя дар бораи он ки бо маълумот дар рох аз замима ба диск чй мешавад.
  • Кай шумо бояд директорияи дорои файлро ҳамоҳанг созед - ҷавоб ба саволи кай бояд истифода шавад fsync() барои директорияҳо. Барои ба таври мухтасар баён кардани ин, маълум мешавад, ки шумо бояд ин корро ҳангоми сохтани файли нав анҷом диҳед ва сабаби ин тавсия дар он аст, ки дар Linux истинодҳои зиёде ба як файл вуҷуд доранд.
  • SQL Server дар Linux: FUA Internals — ин ҷо тавсифи он аст, ки чӣ тавр нигоҳдории доимии маълумот дар SQL Server дар платформаи Linux амалӣ карда мешавад. Дар ин ҷо якчанд муқоисаҳои ҷолиб байни зангҳои системаи Windows ва Linux мавҷуданд. Ман қариб боварӣ дорам, ки маҳз ба шарофати ин мавод ман дар бораи оптимизатсияи FUA-и XFS фаҳмидам.

Оё шумо маълумотеро гум кардаед, ки ба назари шумо дар диск бехатар нигоҳ дошта шудааст?

Нигоҳдории устувори маълумот ва API-ҳои файли Linux

Нигоҳдории устувори маълумот ва API-ҳои файли Linux

Манбаъ: will.com