پائیدار ڈیٹا اسٹوریج اور لینکس فائل APIs

کلاؤڈ سسٹمز میں ڈیٹا اسٹوریج کی پائیداری پر تحقیق کرتے ہوئے، میں نے یہ یقینی بنانے کے لیے خود کو جانچنے کا فیصلہ کیا کہ میں بنیادی چیزوں کو سمجھتا ہوں۔ میں NVMe تفصیلات پڑھ کر شروع کیا۔ یہ سمجھنے کے لیے کہ پائیدار ڈیٹا سٹوریج کے بارے میں کیا ضمانت دیتا ہے (یعنی اس بات کی ضمانت دیتا ہے کہ سسٹم کی خرابی کے بعد ڈیٹا دستیاب ہوگا) ہمیں NMVe ڈسکیں دیں۔ میں نے مندرجہ ذیل اہم نتائج اخذ کیے: ڈیٹا کو اس لمحے سے خراب سمجھا جانا چاہیے جب سے ڈیٹا لکھنے کا حکم دیا جاتا ہے جب تک کہ اسے اسٹوریج میڈیم پر نہیں لکھا جاتا۔ تاہم، زیادہ تر پروگرام ڈیٹا کو ریکارڈ کرنے کے لیے بہت خوشی سے سسٹم کالز کا استعمال کرتے ہیں۔

اس پوسٹ میں، میں لینکس فائل APIs کے ذریعہ فراہم کردہ مستقل اسٹوریج میکانزم کو تلاش کرتا ہوں۔ ایسا لگتا ہے کہ یہاں سب کچھ آسان ہونا چاہئے: پروگرام کمانڈ کو کال کرتا ہے۔ write()، اور اس کمانڈ کے مکمل ہونے کے بعد، ڈیٹا محفوظ طریقے سے ڈسک میں محفوظ ہو جائے گا۔ لیکن write() صرف ایپلیکیشن ڈیٹا کو RAM میں موجود کرنل کیشے میں کاپی کرتا ہے۔ سسٹم کو ڈسک پر ڈیٹا لکھنے پر مجبور کرنے کے لیے، آپ کو کچھ اضافی میکانزم استعمال کرنے کی ضرورت ہے۔

پائیدار ڈیٹا اسٹوریج اور لینکس فائل APIs

مجموعی طور پر، یہ مواد ان نوٹوں کا مجموعہ ہے جو میں نے اپنی دلچسپی کے موضوع پر سیکھا ہے۔ اگر ہم سب سے اہم چیز کے بارے میں بہت مختصر بات کرتے ہیں، تو یہ پتہ چلتا ہے کہ پائیدار ڈیٹا اسٹوریج کو منظم کرنے کے لیے آپ کو کمانڈ استعمال کرنے کی ضرورت ہے۔ fdatasync() یا جھنڈے کے ساتھ فائلیں کھولیں۔ O_DSYNC. اگر آپ اس بارے میں مزید جاننے میں دلچسپی رکھتے ہیں کہ کوڈ سے ڈسک تک ڈیٹا کا کیا ہوتا ہے، تو اس پر ایک نظر ڈالیں۔ یہ مضمون

رائٹ() فنکشن استعمال کرنے کی خصوصیات

سسٹم کال۔ write() معیار میں بیان کیا گیا ہے۔ آئی ای ای ای پوسکس فائل ڈسکرپٹر پر ڈیٹا لکھنے کی کوشش کے طور پر۔ کامیاب تکمیل کے بعد 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 KiB لکھتا ہے، اور fdatasync() - 16 KiB)۔ نیز، مجھے پتہ چلا کہ 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 فائل انٹیگریٹی کمپلیشن" اور "ڈیٹا انٹیگریٹی کمپلیشن" کہا جاتا ہے۔ اس نقطہ نظر کا بنیادی فائدہ یہ ہے کہ ڈیٹا کی سالمیت کو یقینی بنانے کے لیے، آپ کو دو کے بجائے صرف ایک سسٹم کال کرنے کی ضرورت ہے (مثال کے طور پر - 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 سرور میں ڈیٹا اسٹوریج کو کس طرح لاگو کیا جاتا ہے۔ یہاں ونڈوز اور لینکس سسٹم کالز کے درمیان کچھ دلچسپ موازنے ہیں۔ مجھے تقریباً یقین ہے کہ اس مواد کی بدولت میں نے XFS کی FUA اصلاح کے بارے میں سیکھا۔

کیا آپ نے وہ ڈیٹا کھو دیا ہے جو آپ کے خیال میں ڈسک پر محفوظ طریقے سے محفوظ تھا؟

پائیدار ڈیٹا اسٹوریج اور لینکس فائل APIs

پائیدار ڈیٹا اسٹوریج اور لینکس فائل APIs

ماخذ: www.habr.com