நீடித்த தரவு சேமிப்பு மற்றும் லினக்ஸ் கோப்பு APIகள்

மேகக்கணி அமைப்புகளில் தரவு சேமிப்பகத்தின் நிலைத்தன்மையை ஆராய்ச்சி செய்யும் போது, ​​அடிப்படை விஷயங்களை நான் புரிந்து கொண்டேன் என்பதை உறுதிப்படுத்த என்னை நானே சோதிக்க முடிவு செய்தேன். நான் NVMe விவரக்குறிப்பைப் படிப்பதன் மூலம் தொடங்கப்பட்டது நிலையான தரவு சேமிப்பிடம் (அதாவது, கணினி செயலிழந்த பிறகு தரவு கிடைக்கும் என்பதற்கு உத்தரவாதம்) என்ன உத்தரவாதம் என்பதை புரிந்து கொள்ள, NMVe வட்டுகளை எங்களுக்கு வழங்கவும். நான் பின்வரும் முக்கிய முடிவுகளை எடுத்தேன்: தரவை எழுதுவதற்கான கட்டளை கொடுக்கப்பட்ட தருணத்திலிருந்து சேமிப்பக ஊடகத்தில் எழுதப்படும் தருணம் வரை தரவு சேதமடைந்ததாகக் கருதப்பட வேண்டும். இருப்பினும், பெரும்பாலான நிரல்கள் தரவுகளை பதிவு செய்ய கணினி அழைப்புகளை மிகவும் மகிழ்ச்சியுடன் பயன்படுத்துகின்றன.

இந்த இடுகையில், Linux கோப்பு APIகள் வழங்கும் நிலையான சேமிப்பக வழிமுறைகளை நான் ஆராய்கிறேன். இங்கே எல்லாம் எளிமையாக இருக்க வேண்டும் என்று தோன்றுகிறது: நிரல் கட்டளையை அழைக்கிறது write(), மற்றும் இந்த கட்டளை முடிந்ததும், தரவு பாதுகாப்பாக வட்டில் சேமிக்கப்படும். ஆனாலும் write() RAM இல் உள்ள கர்னல் தற்காலிக சேமிப்பிற்கு மட்டுமே பயன்பாட்டுத் தரவை நகலெடுக்கிறது. வட்டில் தரவை எழுத கணினியை கட்டாயப்படுத்த, நீங்கள் சில கூடுதல் வழிமுறைகளைப் பயன்படுத்த வேண்டும்.

நீடித்த தரவு சேமிப்பு மற்றும் லினக்ஸ் கோப்பு APIகள்

ஒட்டுமொத்தமாக, இந்த உள்ளடக்கம் எனக்கு ஆர்வமுள்ள ஒரு தலைப்பில் நான் கற்றுக்கொண்டது தொடர்பான குறிப்புகளின் தொகுப்பாகும். மிக முக்கியமான விஷயத்தைப் பற்றி நாங்கள் மிகவும் சுருக்கமாகப் பேசினால், நிலையான தரவு சேமிப்பகத்தை ஒழுங்கமைக்க நீங்கள் கட்டளையைப் பயன்படுத்த வேண்டும். fdatasync() அல்லது கொடியுடன் கோப்புகளைத் திறக்கவும் O_DSYNC. குறியீட்டிலிருந்து வட்டுக்குச் செல்லும் வழியில் தரவு என்ன நடக்கிறது என்பதைப் பற்றி மேலும் அறிய நீங்கள் ஆர்வமாக இருந்தால், அதைப் பாருங்கள் இந்த கட்டுரை.

எழுது() செயல்பாட்டைப் பயன்படுத்துவதற்கான அம்சங்கள்

கணினி அழைப்பு write() தரநிலையில் வரையறுக்கப்பட்டுள்ளது IEEE POSIX ஒரு கோப்பு விளக்கத்திற்கு தரவை எழுதும் முயற்சியாக. வெற்றிகரமாக முடித்த பிறகு write() தரவு வாசிப்புச் செயல்பாடுகள் முன்பு எழுதப்பட்ட பைட்டுகளையே திருப்பி அனுப்ப வேண்டும், மற்ற செயல்முறைகள் அல்லது த்ரெட்களில் இருந்து தரவு அணுகப்பட்டாலும் இதைச் செய்கிறது (இங்கே POSIX தரநிலையின் தொடர்புடைய பிரிவு). இது, இயல்பான கோப்பு செயல்பாடுகளுடன் த்ரெட்கள் எவ்வாறு தொடர்பு கொள்கின்றன என்ற பிரிவில், இரண்டு த்ரெட்கள் ஒவ்வொன்றும் இந்த செயல்பாடுகளை அழைத்தால், ஒவ்வொரு அழைப்பும் மற்ற அழைப்பின் அனைத்து நியமிக்கப்பட்ட விளைவுகளையும் பார்க்க வேண்டும் அல்லது எதுவும் இல்லை என்று ஒரு குறிப்பு உள்ளது. இல்லை. விளைவுகள். அனைத்து கோப்பு I/O செயல்பாடுகளும் அவை செயல்படும் ஆதாரத்தின் மீது பூட்டு வைத்திருக்க வேண்டும் என்ற முடிவுக்கு இது வழிவகுக்கிறது.

இது அறுவை சிகிச்சை என்று அர்த்தமா? write() அது அணுவா? தொழில்நுட்பக் கண்ணோட்டத்தில், ஆம். தரவு வாசிப்பு செயல்பாடுகள் எழுதப்பட்டவை அனைத்தையும் அல்லது எதையும் திரும்பப் பெற வேண்டும் write(). ஆனால் ஆபரேஷன் write(), தரநிலையின்படி, அது எழுதும்படி கேட்கப்பட்ட அனைத்தையும் எழுதி முடிக்க வேண்டிய அவசியமில்லை. அவள் தரவின் ஒரு பகுதியை மட்டுமே எழுத அனுமதிக்கப்படுகிறாள். எடுத்துக்காட்டாக, ஒரே கோப்பு விவரிப்பாளரால் விவரிக்கப்பட்டுள்ள கோப்பில் 1024 பைட்டுகள் சேர்க்கும் இரண்டு த்ரெட்கள் எங்களிடம் இருக்கலாம். தரநிலையின் பார்வையில், ஒவ்வொரு எழுதும் செயல்பாடும் கோப்பில் ஒரு பைட்டை மட்டுமே சேர்க்கும் போது ஏற்றுக்கொள்ளக்கூடிய முடிவு இருக்கும். இந்த செயல்பாடுகள் அணுவாக இருக்கும், ஆனால் அவை முடிந்த பிறகு, அவர்கள் கோப்பில் எழுதிய தரவு கலக்கப்படும். இங்கே ஸ்டாக் ஓவர்ஃப்ளோவில் இந்த தலைப்பில் மிகவும் சுவாரஸ்யமான விவாதம்.

fsync() மற்றும் fdatasync() செயல்பாடுகள்

வட்டில் தரவைச் சுத்தப்படுத்த எளிதான வழி செயல்பாட்டை அழைப்பதாகும் fsync(). இந்த செயல்பாடு அனைத்து மாற்றியமைக்கப்பட்ட தொகுதிகளையும் தற்காலிக சேமிப்பிலிருந்து வட்டுக்கு மாற்ற இயக்க முறைமையைக் கேட்கிறது. இதில் அனைத்து கோப்பு மெட்டாடேட்டாவும் (அணுகல் நேரம், கோப்பு மாற்றும் நேரம் மற்றும் பல) அடங்கும். இந்த மெட்டாடேட்டா அரிதாகவே தேவைப்படும் என்று நான் நம்புகிறேன், எனவே இது உங்களுக்கு முக்கியமில்லை என்று தெரிந்தால், நீங்கள் செயல்பாட்டைப் பயன்படுத்தலாம் fdatasync(). தி உதவி மீது fdatasync() இந்தச் செயல்பாட்டின் செயல்பாட்டின் போது, ​​"பின்வரும் தரவு வாசிப்பு செயல்பாடுகளின் சரியான செயல்பாட்டிற்குத் தேவையான" மெட்டாடேட்டாவின் அளவு வட்டில் சேமிக்கப்படும் என்று கூறப்படுகிறது. இதைத்தான் பெரும்பாலான பயன்பாடுகள் கவனிக்கின்றன.

இங்கே எழக்கூடிய ஒரு சிக்கல் என்னவென்றால், சாத்தியமான தோல்விக்குப் பிறகு கோப்பு கண்டறியப்படும் என்பதற்கு இந்த வழிமுறைகள் உத்தரவாதம் அளிக்காது. குறிப்பாக, ஒரு புதிய கோப்பை உருவாக்கும் போது, ​​நீங்கள் அழைக்க வேண்டும் fsync() அதைக் கொண்டிருக்கும் அடைவுக்கு. இல்லையெனில், தோல்விக்குப் பிறகு, இந்த கோப்பு இல்லை என்று மாறிவிடும். இதற்குக் காரணம், UNIX இல், கடினமான இணைப்புகளைப் பயன்படுத்துவதால், ஒரு கோப்பு பல கோப்பகங்களில் இருக்கலாம். எனவே, அழைக்கும் போது fsync() எந்த கோப்பகத் தரவையும் வட்டில் சுத்தப்படுத்த வேண்டும் என்பதை அறிய ஒரு கோப்பிற்கு வழி இல்லை (இங்கே இதைப் பற்றி மேலும் படிக்கலாம்). ext4 கோப்பு முறைமை திறன் கொண்டது போல் தெரிகிறது தானாக விண்ணப்பிக்க fsync() தொடர்புடைய கோப்புகளைக் கொண்ட கோப்பகங்களுக்கு, ஆனால் மற்ற கோப்பு முறைமைகளில் இது இருக்காது.

இந்த பொறிமுறையானது வெவ்வேறு கோப்பு முறைமைகளில் வேறுபட்ட முறையில் செயல்படுத்தப்படலாம். நான் பயன்படுத்தினேன் blktrace ext4 மற்றும் XFS கோப்பு முறைமைகளில் என்ன வட்டு செயல்பாடுகள் பயன்படுத்தப்படுகின்றன என்பதை அறிய. கோப்பு உள்ளடக்கங்கள் மற்றும் கோப்பு முறைமை ஜர்னல் ஆகிய இரண்டிற்கும் வட்டுக்கு வழக்கமான எழுதும் கட்டளைகளை வழங்குகின்றன, தற்காலிக சேமிப்பை பறித்து, மற்றும் ஒரு FUA (ஃபோர்ஸ் யூனிட் அணுகல், தரவை நேரடியாக வட்டில் எழுதுதல், தற்காலிக சேமிப்பைத் தவிர்த்து) ஜர்னலுக்கு எழுதுவதன் மூலம் வெளியேறவும். பரிவர்த்தனை நடந்ததை உறுதி செய்வதற்காக அவர்கள் ஒருவேளை இதைச் செய்கிறார்கள். FUA ஐ ஆதரிக்காத டிரைவ்களில், இது இரண்டு கேச் ஃப்ளஷ்களை ஏற்படுத்துகிறது. எனது சோதனைகள் அதைக் காட்டியது fdatasync() கொஞ்சம் வேகமாக fsync(). பயன்பாடு blktrace என்று குறிப்பிடுகிறது fdatasync() வழக்கமாக குறைவான தரவை வட்டில் எழுதுகிறது (ext4 இல் fsync() 20 கிபி எழுதுகிறார், மற்றும் fdatasync() - 16 கிபி). மேலும், XFS ext4 ஐ விட சற்று வேகமானது என்பதைக் கண்டறிந்தேன். மற்றும் இங்கே உதவியுடன் blktrace என்று கண்டுபிடிக்க முடிந்தது fdatasync() குறைந்த தரவை வட்டுக்கு அனுப்புகிறது (XFS இல் 4 KiB).

fsync() ஐப் பயன்படுத்தும் போது எழும் தெளிவற்ற சூழ்நிலைகள்

நான் மூன்று தெளிவற்ற சூழ்நிலைகளைப் பற்றி சிந்திக்க முடியும் fsync()நான் நடைமுறையில் சந்தித்தது.

இதுபோன்ற முதல் வழக்கு 2008 இல் நடந்தது. அதிக எண்ணிக்கையிலான கோப்புகள் வட்டில் எழுதப்பட்டால் பயர்பாக்ஸ் 3 இடைமுகம் உறைந்தது. சிக்கல் என்னவென்றால், இடைமுகத்தை செயல்படுத்துவது அதன் நிலையைப் பற்றிய தகவல்களைச் சேமிக்க SQLite தரவுத்தளத்தைப் பயன்படுத்தியது. இடைமுகத்தில் ஏற்படும் ஒவ்வொரு மாற்றத்திற்கும் பிறகு, செயல்பாடு அழைக்கப்படுகிறது fsync(), இது நிலையான தரவு சேமிப்பிற்கு நல்ல உத்தரவாதத்தை அளித்தது. பின்னர் பயன்படுத்தப்படும் ext3 கோப்பு முறைமையில், செயல்பாடு fsync() கணினியில் உள்ள அனைத்து "அழுக்கு" பக்கங்களையும் வட்டில் கொட்டியது, தொடர்புடைய கோப்புடன் தொடர்புடையவை மட்டுமல்ல. இதன் பொருள் பயர்பாக்ஸில் ஒரு பொத்தானைக் கிளிக் செய்வதன் மூலம் மெகாபைட் தரவு ஒரு காந்த வட்டில் எழுதப்படும், இது பல வினாடிகள் ஆகலாம். பிரச்சனைக்கான தீர்வு, நான் புரிந்து கொண்ட வரையில் அது தரவுத்தளத்துடன் பணியை ஒத்திசைவற்ற பின்னணி பணிகளுக்கு மாற்றுவது பொருள். இதன் பொருள் பயர்பாக்ஸ் முன்பு உண்மையில் தேவைப்பட்டதை விட கடுமையான சேமிப்பக தேவைகளை செயல்படுத்தியது, மேலும் 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 கொடிகளைப் பயன்படுத்தி கோப்புகளைத் திறக்கிறது

நிலையான தரவு சேமிப்பகத்தை வழங்கும் லினக்ஸ் வழிமுறைகள் பற்றிய விவாதத்திற்கு வருவோம். அதாவது, நாங்கள் கொடியைப் பயன்படுத்துவது பற்றி பேசுகிறோம் O_SYNC அல்லது கொடி O_DSYNC கணினி அழைப்பைப் பயன்படுத்தி கோப்புகளைத் திறக்கும் போது திறந்த (). இந்த அணுகுமுறையின் மூலம், ஒவ்வொரு கட்டளைக்குப் பிறகும் ஒவ்வொரு தரவு எழுதும் செயல்பாடும் செய்யப்படுகிறது write() கணினிக்கு அதற்கேற்ப கட்டளைகள் வழங்கப்படுகின்றன fsync() и fdatasync(). தி POSIX விவரக்குறிப்புகள் இது "Synchronized I/O File Integrity Completion" மற்றும் "Data Integrity Completion" என்று அழைக்கப்படுகிறது. இந்த அணுகுமுறையின் முக்கிய நன்மை என்னவென்றால், தரவு ஒருமைப்பாட்டை உறுதிப்படுத்த, நீங்கள் இரண்டு முறைக்கு பதிலாக ஒரு கணினி அழைப்பை மட்டுமே செய்ய வேண்டும் (உதாரணமாக - write() и fdatasync()) இந்த அணுகுமுறையின் முக்கிய தீமை என்னவென்றால், தொடர்புடைய கோப்பு விளக்கத்தைப் பயன்படுத்தி அனைத்து எழுத்துகளும் ஒத்திசைக்கப்படும், இது பயன்பாட்டுக் குறியீட்டைக் கட்டமைக்கும் திறனைக் கட்டுப்படுத்தும்.

O_DIRECT கொடியுடன் நேரடி I/O ஐப் பயன்படுத்துதல்

கணினி அழைப்பு open() கொடியை ஆதரிக்கிறது O_DIRECT, இது இயக்க முறைமை தற்காலிக சேமிப்பை புறக்கணித்து I/O செயல்பாடுகளை வட்டுடன் நேரடியாக தொடர்பு கொண்டு செயல்பட வடிவமைக்கப்பட்டுள்ளது. இது, பல சந்தர்ப்பங்களில், நிரலால் வழங்கப்பட்ட எழுதும் கட்டளைகள் வட்டுடன் பணிபுரியும் நோக்கில் நேரடியாக கட்டளைகளாக மொழிபெயர்க்கப்படும். ஆனால், பொதுவாக, இந்த பொறிமுறையானது செயல்பாடுகளுக்கு மாற்றாக இல்லை fsync() அல்லது fdatasync(). வட்டு தானே முடியும் என்பதே உண்மை ஒத்திவைத்தல் அல்லது தற்காலிக சேமிப்பு தொடர்புடைய தரவு எழுதும் கட்டளைகள். மேலும், விஷயங்களை மோசமாக்க, சில சிறப்பு சந்தர்ப்பங்களில் கொடியைப் பயன்படுத்தும் போது I/O செயல்பாடுகள் செய்யப்படுகின்றன O_DIRECT, ஒளிபரப்பு பாரம்பரிய இடையக செயல்பாடுகளில். இந்த சிக்கலை தீர்க்க எளிதான வழி, கோப்புகளைத் திறக்க கொடியைப் பயன்படுத்துவதாகும் O_DSYNC, ஒவ்வொரு எழுதும் செயலையும் தொடர்ந்து அழைப்பு வரும் என்று அர்த்தம் fdatasync().

XFS கோப்பு முறைமை சமீபத்தில் "வேகமான பாதையை" சேர்த்தது O_DIRECT|O_DSYNC- தரவு பதிவு. ஒரு தொகுதி மீண்டும் எழுதப்பட்டால் O_DIRECT|O_DSYNC, பின்னர் XFS, தற்காலிக சேமிப்பை சுத்தப்படுத்துவதற்குப் பதிலாக, சாதனம் அதை ஆதரித்தால் FUA எழுதும் கட்டளையை இயக்கும். பயன்பாட்டைப் பயன்படுத்தி இதைச் சரிபார்த்தேன் blktrace லினக்ஸ் 5.4/உபுண்டு 20.04 கணினியில். இந்த அணுகுமுறை மிகவும் திறமையானதாக இருக்க வேண்டும், ஏனெனில் பயன்படுத்தப்படும் போது, ​​குறைந்தபட்ச அளவு தரவு வட்டில் எழுதப்படுகிறது மற்றும் ஒரு செயல்பாடு பயன்படுத்தப்படுகிறது, மாறாக இரண்டு (கேச் எழுதுதல் மற்றும் சுத்தப்படுத்துதல்). அதற்கான இணைப்பைக் கண்டேன் இணைப்பு இந்த பொறிமுறையை செயல்படுத்தும் 2018 கர்னல். மற்ற கோப்பு முறைமைகளுக்கு இந்த தேர்வுமுறையைப் பயன்படுத்துவது பற்றி சில விவாதங்கள் உள்ளன, ஆனால் எனக்குத் தெரிந்தவரை, XFS மட்டுமே இதுவரை இதை ஆதரிக்கும் ஒரே கோப்பு முறைமையாகும்.

sync_file_range() செயல்பாடு

லினக்ஸில் சிஸ்டம் கால் உள்ளது sync_file_range(), இது முழு கோப்பையும் இல்லாமல், கோப்பின் ஒரு பகுதியை மட்டும் வட்டில் ஃப்ளஷ் செய்ய அனுமதிக்கிறது. இந்த அழைப்பு ஒத்திசைவற்ற தரவு பறிப்பைத் தொடங்குகிறது மற்றும் அது முடிவடையும் வரை காத்திருக்காது. ஆனால் சான்றிதழில் sync_file_range() அணி "மிகவும் ஆபத்தானது" என்று கூறப்படுகிறது. அதைப் பயன்படுத்த பரிந்துரைக்கப்படவில்லை. அம்சங்கள் மற்றும் ஆபத்துகள் sync_file_range() மிகவும் நன்றாக விவரிக்கப்பட்டுள்ளது இந்த பொருள். குறிப்பாக, இந்த அழைப்பு RocksDB ஐ கர்னல் வட்டில் அழுக்குத் தரவை ஃப்ளஷ் செய்யும் போது கட்டுப்படுத்த பயன்படுத்துகிறது. ஆனால் அதே நேரத்தில், நிலையான தரவு சேமிப்பகத்தை உறுதிப்படுத்த, இதுவும் பயன்படுத்தப்படுகிறது fdatasync(). தி குறியீடு இந்த தலைப்பில் RocksDB சில சுவாரஸ்யமான கருத்துக்களைக் கொண்டுள்ளது. உதாரணமாக, அழைப்பு என்று தோன்றுகிறது sync_file_range() ZFS ஐப் பயன்படுத்தும் போது, ​​அது தரவுகளை வட்டில் ஃப்ளஷ் செய்யாது. அரிதாகப் பயன்படுத்தப்படும் குறியீட்டில் பிழைகள் இருக்கலாம் என்று அனுபவம் எனக்குச் சொல்கிறது. எனவே, முற்றிலும் தேவைப்படாவிட்டால், இந்த கணினி அழைப்பைப் பயன்படுத்துவதற்கு எதிராக நான் அறிவுறுத்துகிறேன்.

தரவு நிலைத்தன்மையை உறுதிப்படுத்த உதவும் கணினி அழைப்புகள்

தரவு நிலைத்தன்மையை உறுதி செய்யும் I/O செயல்பாடுகளைச் செய்ய மூன்று அணுகுமுறைகள் பயன்படுத்தப்படலாம் என்ற முடிவுக்கு வந்துள்ளேன். அவர்கள் அனைவருக்கும் ஒரு செயல்பாட்டு அழைப்பு தேவைப்படுகிறது 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 (இது அதிகாரப்பூர்வமற்ற தரவு, என்னால் அதை உறுதிப்படுத்த முடியவில்லை). சேமிப்பிற்கும் இதுவே செல்கிறது ஜிசிபி பெர்சிஸ்டண்ட் டிஸ்க் (இது ஏற்கனவே அதிகாரப்பூர்வ தகவல், சோதனைகள் மூலம் உறுதிப்படுத்தப்பட்டுள்ளது). மற்ற நிபுணர்களும் அதையே செய்துள்ளனர் கவனிப்பு, பல்வேறு வட்டுகளுடன் தொடர்புடையது.
  2. குறைவான கணினி அழைப்புகள், அதிக செயல்திறன் (ஆதாயம் சுமார் 5% ஆக இருக்கலாம்). சவால் போல் தெரிகிறது open() கொடியுடன் O_DSYNC அல்லது அழைக்கவும் pwritev2() கொடியுடன் RWF_SYNC அழைப்பை விட வேகமாக fdatasync(). ஒரே பிரச்சனையை (இரண்டிற்கு பதிலாக ஒரு அழைப்பு) தீர்க்க குறைவான சிஸ்டம் அழைப்புகள் செய்யப்பட வேண்டும் என்பதில் இந்த அணுகுமுறை ஒரு பங்கு வகிக்கிறது என்று நான் சந்தேகிக்கிறேன். ஆனால் செயல்திறனில் உள்ள வேறுபாடு மிகவும் சிறியது, எனவே நீங்கள் அதை முற்றிலும் புறக்கணித்து, அதன் தர்க்கத்தை சிக்கலாக்காத பயன்பாட்டில் ஏதாவது ஒன்றைப் பயன்படுத்தலாம்.

நிலையான தரவு சேமிப்பகம் என்ற தலைப்பில் நீங்கள் ஆர்வமாக இருந்தால், இங்கே சில பயனுள்ள பொருட்கள் உள்ளன:

  • I/O அணுகல் முறைகள் - உள்ளீடு/வெளியீட்டு வழிமுறைகளின் அடிப்படைகளின் கண்ணோட்டம்.
  • தரவு வட்டை அடைவதை உறுதி செய்தல் — பயன்பாட்டிலிருந்து வட்டுக்கு செல்லும் வழியில் தரவுகளுக்கு என்ன நடக்கிறது என்பது பற்றிய கதை.
  • கொண்டிருக்கும் கோப்பகத்தை எப்போது fsync செய்ய வேண்டும் - எப்போது பயன்படுத்த வேண்டும் என்ற கேள்விக்கான பதில் fsync() அடைவுகளுக்கு. இதை சுருக்கமாகச் சொல்வதானால், புதிய கோப்பை உருவாக்கும் போது இதைச் செய்ய வேண்டும் என்று மாறிவிடும், மேலும் லினக்ஸில் ஒரே கோப்பில் பல குறிப்புகள் இருக்கலாம் என்பதே இந்த பரிந்துரைக்கான காரணம்.
  • லினக்ஸில் SQL சர்வர்: FUA இன்டர்னல்ஸ் — லினக்ஸ் இயங்குதளத்தில் SQL சர்வரில் நிலையான தரவு சேமிப்பகம் எவ்வாறு செயல்படுத்தப்படுகிறது என்பதற்கான விளக்கம் இங்கே உள்ளது. விண்டோஸ் மற்றும் லினக்ஸ் சிஸ்டம் அழைப்புகளுக்கு இடையே சில சுவாரஸ்யமான ஒப்பீடுகள் இங்கே உள்ளன. XFS இன் FUA ஆப்டிமைசேஷன் பற்றி நான் கற்றுக்கொண்டது இந்த விஷயத்திற்கு நன்றி என்று நான் உறுதியாக நம்புகிறேன்.

வட்டில் பாதுகாப்பாகச் சேமிக்கப்பட்டதாக நீங்கள் நினைக்கும் தரவை இழந்துவிட்டீர்களா?

நீடித்த தரவு சேமிப்பு மற்றும் லினக்ஸ் கோப்பு APIகள்

நீடித்த தரவு சேமிப்பு மற்றும் லினக்ஸ் கோப்பு APIகள்

ஆதாரம்: www.habr.com