Depo done dirab ak API Linux File

Pandan m ap fè rechèch sou dirab depo done nan sistèm nwaj yo, mwen deside teste tèt mwen pou m asire m ke m konprann bagay debaz yo. mwen te kòmanse pa li spesifikasyon NVMe a yo nan lòd yo konprann ki garanti konsènan depo done dirab (ki se, garanti ke done yo ap disponib apre yon echèk sistèm) ban nou disk NMVe. Mwen te fè konklizyon prensipal sa yo: done yo dwe konsidere kòm domaje depi lè yo bay lòd pou yo ekri done jiska moman sa a yo ekri nan mwayen depo a. Sepandan, pifò pwogram yo byen kontan itilize apèl sistèm pou anrejistre done yo.

Nan pòs sa a, mwen eksplore mekanis depo ki pèsistan yo bay nan API yo fichye Linux. Li sanble ke tout bagay ta dwe senp isit la: pwogram nan rele lòd la write(), epi apre lòd sa a fini, done yo pral byen sove sou disk. Men write() sèlman kopye done aplikasyon an nan kachèt nwayo ki sitiye nan RAM. Pou fòse sistèm nan ekri done sou disk, ou bezwen sèvi ak kèk mekanis adisyonèl.

Depo done dirab ak API Linux File

An jeneral, materyèl sa a se yon koleksyon nòt ki gen rapò ak sa mwen te aprann sou yon sijè ki enterese m. Si nou pale yon ti tan sou bagay ki pi enpòtan an, li sanble ke pou òganize depo done dirab ou bezwen sèvi ak lòd la. fdatasync() oswa louvri dosye ak drapo a O_DSYNC. Si w enterese nan aprann plis sou sa k ap pase done sou wout li soti nan kòd nan disk, gade nan sa a atik.

Karakteristik lè l sèvi avèk fonksyon ekri () la

Sistèm apèl write() defini nan estanda a IEEE POSIX kòm yon tantativ pou ekri done nan yon deskriptè dosye. Apre fini siksè write() Operasyon lekti done yo dwe retounen egzakteman byte yo te ekri deja, fè sa menm si done yo jwenn aksè nan lòt pwosesis oswa fil (isit la seksyon ki enpòtan nan estanda POSIX la). Isit la, nan seksyon sou fason fil yo kominike avèk operasyon dosye nòmal, gen yon nòt ki di ke si de fil chak rele fonksyon sa yo, Lè sa a, chak apèl dwe wè swa tout konsekans yo deziyen nan lòt apèl la, oswa pa gen okenn ditou. konsekans. Sa a mennen nan konklizyon ke tout operasyon I/O dosye yo dwe kenbe yon seri sou resous yo ap opere sou yo.

Èske sa vle di ke operasyon an write() èske li atomik? Soti nan yon pwen de vi teknik, wi. Operasyon lekti done yo dwe retounen swa tout oswa anyen nan sa ki te ekri avèk yo write(). Men, operasyon an write(), dapre estanda a, pa nesesèman dwe fini pa ekri tout sa yo te mande yo ekri. Li gen dwa ekri sèlman yon pati nan done yo. Pou egzanp, nou ta ka gen de fil chak ajoute 1024 octets nan yon dosye ki dekri pa menm deskriptè a fichye. Soti nan pwen de vi nan estanda a, yon rezilta akseptab yo pral lè chak operasyon ekri ka ajoute sèlman yon byte nan dosye a. Operasyon sa yo ap rete atomik, men apre yo fin ranpli, done yo te ekri nan dosye a pral melanje. Isit la diskisyon trè enteresan sou sijè sa a sou Stack Overflow.

Fonksyon fsync() ak fdatasync().

Fason ki pi fasil pou kole done sou disk se rele fonksyon an fsync(). Fonksyon sa a mande sistèm operasyon an transfere tout blòk modifye nan kachèt la nan disk. Sa gen ladann tout metadata fichye yo (tan aksè, tan modifikasyon fichye, ak sou sa). Mwen kwè ke metadata sa yo raman nesesè, kidonk si ou konnen li pa enpòtan pou ou, ou ka itilize fonksyon an. fdatasync(). Nan ede sou fdatasync() yo di ke pandan operasyon an nan fonksyon sa a, se yon kantite metadata sa yo sove sou disk ki "nesesè pou egzekisyon kòrèk la nan operasyon lekti done sa yo." Ak sa a se egzakteman sa pifò aplikasyon yo pran swen.

Youn nan pwoblèm ki ka leve isit la se ke mekanis sa yo pa garanti ke dosye a pral dekouvri apre yon echèk posib. An patikilye, lè w ap kreye yon nouvo dosye, ou bezwen rele fsync() pou anyè ki genyen li. Sinon, apre yon echèk, li ka vire soti ke dosye sa a pa egziste. Rezon ki fè sa a se ke nan UNIX, akòz itilizasyon lyen difisil, yon dosye ka egziste nan plizyè repèrtwar. Se poutèt sa, lè w ap rele fsync() pa gen okenn fason pou yon fichye konnen ki done anyè yo ta dwe tou vide sou disk (isit la Ou ka li plis sou sa). Li sanble ke sistèm fichye ext4 la kapab otomatikman itilize fsync() nan repèrtwar ki gen fichye korespondan yo, men sa ka pa ka a ak lòt sistèm dosye.

Mekanis sa a ka aplike yon fason diferan sou diferan sistèm dosye. Mwen te itilize blktrace pou aprann sou ki operasyon disk yo itilize nan sistèm fichye ext4 ak XFS. Tou de bay kòmandman ekri regilye sou disk pou tou de sa ki nan dosye a ak jounal sistèm dosye a, vide kachèt la, epi sòti lè yo fè yon FUA (Force Unit Access, ekri done dirèkteman sou disk, kontoune kachèt la) ekri nan jounal la. Yo pwobableman fè sa yo nan lòd yo konfime ke tranzaksyon an te fèt. Sou kondui ki pa sipòte FUA, sa lakòz de flush kachèt. Eksperyans mwen yo te montre sa fdatasync() yon ti kras pi vit fsync(). Itilite blktrace endike sa fdatasync() anjeneral ekri mwens done sou disk (nan ext4 fsync() ekri 20 KiB, epi fdatasync() - 16 Ko). Epitou, mwen te jwenn ke XFS se yon ti kras pi vit pase ext4. Ak isit la ak èd la blktrace jere yo chèche konnen sa fdatasync() lage mwens done sou disk (4 KiB nan XFS).

Sitiyasyon ambigu ki parèt lè w ap itilize fsync()

Mwen ka panse a twa sitiyasyon ambigu konsènan fsync()ke mwen te rankontre nan pratik.

Premye ka sa a te fèt an 2008. Lè sa a, koòdone Firefox 3 te jele si yo te ekri yon gwo kantite dosye sou disk. Pwoblèm lan te ke aplikasyon an nan koòdone a te itilize yon baz done SQLite nan magazen enfòmasyon sou eta li yo. Apre chak chanjman ki te fèt nan koòdone a, yo te rele fonksyon an fsync(), ki te bay bon garanti nan depo done ki estab. Nan sistèm nan dosye ext3 Lè sa a, itilize, fonksyon an fsync() jete tout paj "sal" nan sistèm nan sou disk, epi yo pa sèlman sa yo ki te gen rapò ak dosye ki koresponn lan. Sa vle di ke klike sou yon bouton nan Firefox ka deklanche megabyte done yo dwe ekri sou yon disk mayetik, sa ki ka pran anpil segonn. Solisyon an nan pwoblèm nan, osi lwen ke mwen konprann soti nan nan sa a materyèl te transfere travay ak baz done a nan travay background asynchrone. Sa vle di ke Firefox te deja aplike kondisyon depo ki pi sevè pase sa te vrèman nesesè, ak karakteristik yo nan sistèm nan dosye ext3 sèlman agrave pwoblèm sa a.

Dezyèm pwoblèm nan te fèt an 2009. Lè sa a, apre yon aksidan sistèm, itilizatè nouvo sistèm fichye ext4 la te fè fas ak lefèt ke anpil fichye ki fèk kreye te gen longè zewo, men sa pa t rive ak pi gran sistèm fichye ext3 la. Nan paragraf anvan an, mwen te pale sou ki jan ext3 vide twòp done sou disk, ki ralanti bagay yo anpil. fsync(). Pou amelyore sitiyasyon an, nan ext4 sèlman paj sal sa yo ki gen rapò ak yon fichye patikilye yo vide sou disk. Ak done ki soti nan lòt dosye rete nan memwa pou yon tan pi long pase ak ext3. Sa a te fè pou amelyore pèfòmans (pa default, done yo rete nan eta sa a pou 30 segonn, ou ka configured sa a lè l sèvi avèk dirty_expire_centisecs; isit la Ou ka jwenn lòt materyèl sou sa). Sa vle di ke yon gwo kantite done ka irevokabl pèdi apre yon echèk. Solisyon an nan pwoblèm sa a se sèvi ak fsync() nan aplikasyon ki bezwen asire depo done ki estab ak pwoteje yo otank posib kont konsekans echèk yo. Fonksyon fsync() travay pi plis efikasite lè w ap itilize ext4 pase lè w ap itilize ext3. Dezavantaj nan apwòch sa a se ke itilizasyon li yo, tankou anvan, ralanti ekzekisyon an nan kèk operasyon, tankou enstale pwogram. Gade detay sou sa isit la и isit la.

Twazyèm pwoblèm konsènan fsync(), soti nan 2018. Lè sa a, nan kad pwojè PostgreSQL la, li te jwenn ke si fonksyon an fsync() rankontre yon erè, li make paj "sal" kòm "pwòp". Kòm yon rezilta, apèl sa yo fsync() Yo pa fè anyen ak paj sa yo. Poutèt sa, paj modifye yo estoke nan memwa epi yo pa janm ekri sou disk. Sa a se yon dezas reyèl, depi aplikasyon an pral panse ke kèk done yo ekri sou disk la, men an reyalite li pa pral. Echèk sa yo fsync() yo ra, aplikasyon an nan sitiyasyon sa yo ka fè prèske anyen pou konbat pwoblèm nan. Jou sa yo, lè sa rive, PostgreSQL ak lòt aplikasyon fè aksidan. Isit la, nan materyèl la "Èske aplikasyon yo ka refè soti nan echèk fsync?", yo eksplore pwoblèm sa a an detay. Kounye a pi bon solisyon a pwoblèm sa a se sèvi ak Direct I/O ak drapo a O_SYNC oswa ak yon drapo O_DSYNC. Avèk apwòch sa a, sistèm nan pral rapòte erè ki ka rive pandan operasyon ekriti espesifik, men apwòch sa a mande pou aplikasyon an jere tanpon yo tèt li. Li plis sou sa isit la и isit la.

Louvri fichye yo lè l sèvi avèk drapo O_SYNC ak O_DSYNC

Ann retounen nan diskisyon sou mekanis Linux ki bay depo done ki estab. Savwa, nou ap pale sou itilize drapo a O_SYNC oswa drapo O_DSYNC lè w ap louvri dosye lè l sèvi avèk apèl sistèm louvri (). Avèk apwòch sa a, chak operasyon ekri done fèt kòm si apre chak lòd write() yo bay sistèm nan kòmandman kòmsadwa fsync() и fdatasync(). Nan Espesifikasyon POSIX sa yo rele "Synchronized I/O File Entegrity Completion" ak "Done Entegrite Konplete". Avantaj prensipal la nan apwòch sa a se ke pou asire entegrite done, ou sèlman bezwen fè yon apèl sistèm, olye ke de (pa egzanp - write() и fdatasync()). Dezavantaj prensipal la nan apwòch sa a se ke tout ekri lè l sèvi avèk deskriptè dosye ki koresponn lan pral senkronize, sa ki ka limite kapasite nan estrikti kòd aplikasyon an.

Sèvi ak Direct I/O ak drapo O_DIRECT la

Sistèm apèl open() sipòte drapo O_DIRECT, ki fèt pou kontoune kachèt sistèm operasyon an pou fè operasyon I/O pa kominike dirèkteman ak disk la. Sa a, nan anpil ka, vle di ke ekri kòmandman bay pa pwogram nan pral dirèkteman tradui nan kòmandman ki vize a travay ak disk la. Men, an jeneral, mekanis sa a se pa yon ranplasman pou fonksyon fsync() oswa fdatasync(). Reyalite a se ke disk nan tèt li kapab ranvwaye oswa kachèt kòmandman ekri done korespondan yo. Epi, pou fè bagay yo vin pi mal, nan kèk ka espesyal I/O operasyon yo fèt lè w ap itilize drapo a O_DIRECT, emisyon nan operasyon tanpon tradisyonèl yo. Fason ki pi fasil pou rezoud pwoblèm sa a se sèvi ak drapo a pou louvri dosye O_DSYNC, ki pral vle di ke chak operasyon ekri pral swiv pa yon apèl fdatasync().

Li te tounen soti ke sistèm nan dosye XFS dènyèman te ajoute yon "chemen rapid" pou O_DIRECT|O_DSYNC-anrejistreman done. Si yon blòk reekri lè l sèvi avèk O_DIRECT|O_DSYNC, Lè sa a, XFS, olye pou yo vide kachèt la, pral egzekite lòd ekri FUA a si aparèy la sipòte li. Mwen verifye sa a lè l sèvi avèk sèvis piblik la blktrace sou yon sistèm Linux 5.4/Ubuntu 20.04. Apwòch sa a ta dwe pi efikas, depi lè yo itilize, yo ekri yon kantite minimòm done sou disk la epi yo itilize yon sèl operasyon, olye de de (ekri ak vide kachèt la). Mwen jwenn yon lyen pou patch 2018 Kernel, ki aplike mekanis sa a. Gen kèk diskisyon sou aplikasyon optimize sa a nan lòt sistèm dosye tou, men osi lwen ke mwen konnen, XFS se sistèm nan dosye sèlman ki sipòte sa a byen lwen tèlman.

sync_file_range() fonksyon

Linux gen yon apèl sistèm sync_file_range(), ki pèmèt ou vide sèlman yon pati nan dosye a sou disk, olye ke dosye a tout antye. Apèl sa a inisye yon koule done asynchrone epi li pa tann pou li fini. Men, nan sètifika a sync_file_range() yo di ekip la "trè danjere". Li pa rekòmande pou itilize li. Karakteristik ak danje sync_file_range() trè byen dekri nan sa a materyèl. Espesyalman, apèl sa a parèt pou itilize RocksDB pou kontwole lè nwayo a vide done sal sou disk. Men, an menm tan an, asire depo done ki estab, li se tou itilize fdatasync(). Nan kòd RocksDB gen kèk kòmantè enteresan sou sijè sa a. Pou egzanp, li parèt ke apèl la sync_file_range() Lè w ap itilize ZFS, li pa vide done sou disk. Eksperyans di m ke kòd ki raman itilize gen anpil chans pou genyen pinèz. Se poutèt sa, mwen ta konseye kont itilize apèl sistèm sa a sof si absoliman nesesè.

Apèl sistèm ki ede asire pèsistans done yo

Mwen te rive nan konklizyon ke gen twa apwòch ki ka itilize pou fè operasyon I/O ki asire pèsistans done. Yo tout mande pou yon apèl fonksyon fsync() pou anyè kote yo te kreye dosye a. Sa yo se apwòch yo:

  1. Rele yon fonksyon fdatasync() oswa fsync() apre fonksyon write() (li pi bon pou itilize fdatasync()).
  2. Travay ak yon deskriptè dosye louvri ak yon drapo O_DSYNC oswa O_SYNC (pi bon - ak yon drapo O_DSYNC).
  3. Itilizasyon kòmand pwritev2() ak drapo RWF_DSYNC oswa RWF_SYNC (de preferans ak yon drapo RWF_DSYNC).

Nòt pèfòmans

Mwen pa byen mezire pèfòmans plizyè mekanis mwen te egzamine. Diferans mwen remake nan vitès travay yo piti anpil. Sa vle di ke mwen ka mal, e ke nan diferan kondisyon menm bagay la ka pwodwi rezilta diferan. Premyèman, mwen pral pale sou sa ki afekte pèfòmans plis, ak Lè sa a, sa ki afekte pèfòmans mwens.

  1. Ranplase done fichye yo pi vit pase ajoute done nan yon fichye (benefis pèfòmans yo ka 2-100%). Mete done nan yon dosye mande pou chanjman adisyonèl nan metadata fichye a, menm apre yon apèl sistèm fallocate(), men grandè efè sa a ka varye. Mwen rekòmande, pou pi bon pèfòmans, rele fallocate() pou pre-allocation espas ki nesesè yo. Lè sa a, espas sa a dwe klèman ranpli ak zewo epi rele fsync(). Sa a pral asire ke blòk korespondan yo nan sistèm nan dosye yo make kòm "atribye" olye ke "pa alokasyon". Sa a bay yon ti (apeprè 2%) amelyorasyon pèfòmans. Anplis de sa, kèk disk ka gen yon premye aksè pi dousman nan yon blòk pase lòt. Sa vle di ke ranpli espas la ak zewo ka mennen nan yon amelyorasyon siyifikatif (apeprè 100%) nan pèfòmans. An patikilye, sa ka rive ak disk AWS EBS (sa a se done ofisyèl, mwen pa t 'kapab konfime li). Menm bagay la tou ale pou depo Disk ki pèsistan GCP (ak sa a se deja enfòmasyon ofisyèl, konfime pa tès yo). Lòt ekspè yo te fè menm bagay la obsèvasyon, ki gen rapò ak divès kalite disk.
  2. Mwens sistèm apèl, pi wo pèfòmans lan (gain a ka apeprè 5%). Sanble yon defi open() ak drapo O_DSYNC oswa rele pwritev2() ak drapo RWF_SYNC pi vit pase yon apèl fdatasync(). Mwen sispèk ke pwen isit la se ke apwòch sa a jwe yon wòl nan lefèt ke mwens apèl sistèm yo dwe fèt pou rezoud pwoblèm nan menm (yon apèl olye de de). Men, diferans lan nan pèfòmans piti anpil, kidonk, ou ka konplètman inyore li epi sèvi ak yon bagay nan aplikasyon an ki pa pral konplike lojik li yo.

Si w enterese nan sijè a nan depo done dirab, isit la se kèk materyèl itil:

  • Metòd Aksè I/O — BECA de baz yo nan mekanis antre/sòti.
  • Asire done rive nan disk — yon istwa sou sa k ap pase done yo sou wout la soti nan aplikasyon an nan disk la.
  • Ki lè ou ta dwe fsync anyè ki genyen an - repons pou kesyon ki lè pou itilize fsync() pou anyè. Pou mete sa a nan yon Nutshell, li vire soti ke ou bezwen fè sa lè w ap kreye yon nouvo dosye, ak rezon ki fè rekòmandasyon sa a se ke nan Linux ka gen anpil referans nan menm dosye a.
  • SQL sèvè sou Linux: FUA Internals — Men yon deskripsyon sou fason depo done ki pèsistan aplike nan SQL sèvè sou platfòm Linux la. Gen kèk konparezon enteresan ant apèl sistèm Windows ak Linux isit la. Mwen prèske sèten ke se gras a materyèl sa a ke mwen te aprann sou optimize FUA nan XFS.

Èske w pèdi done ou te panse yo te byen estoke sou yon disk?

Depo done dirab ak API Linux File

Depo done dirab ak API Linux File

Sous: www.habr.com