ریڈیس کا استعمال کرتے ہوئے تقسیم شدہ لاکنگ

ارے حبر!

آج ہم Redis کا استعمال کرتے ہوئے تقسیم شدہ لاکنگ کے نفاذ کے بارے میں ایک پیچیدہ مضمون کا ترجمہ آپ کی توجہ میں لاتے ہیں اور آپ کو ایک موضوع کے طور پر Redis کے امکانات کے بارے میں بات کرنے کی دعوت دیتے ہیں۔ کتاب کے مصنف مارٹن کلیپ مین سے سوال میں ریڈ لاک الگورتھم کا تجزیہہائی لوڈ ایپلی کیشنز"، دیا یہاں.

ڈسٹری بیوٹڈ لاکنگ بہت سے ماحول میں استعمال ہونے والا ایک بہت ہی مفید پرائمٹیو ہے جہاں مختلف عمل کو مشترکہ وسائل پر باہمی طور پر خصوصی طور پر کام کرنا چاہیے۔

وہاں بہت سی لائبریریاں اور پوسٹس موجود ہیں جو یہ بیان کرتی ہیں کہ Redis کا استعمال کرتے ہوئے DLM (ڈسٹری بیوٹڈ لاک مینیجر) کو کیسے نافذ کیا جائے، لیکن ہر لائبریری ایک مختلف طریقہ اختیار کرتی ہے اور وہ جو ضمانتیں فراہم کرتی ہیں اس کے مقابلے میں قدرے زیادہ نفیس ڈیزائن کے ساتھ حاصل کیا جا سکتا ہے۔

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

عمل آوری

الگورتھم کی تفصیل پر جانے سے پہلے، ہم ریڈی میڈ نفاذ کے کئی لنک فراہم کرتے ہیں۔ وہ حوالہ کے لئے استعمال کیا جا سکتا ہے.

سیکیورٹی اور دستیابی کی ضمانتیں۔

ہم اپنے ڈیزائن کو صرف تین خصوصیات کے ساتھ ماڈل کرنے جا رہے ہیں جو ہمارے خیال میں تقسیم شدہ لاکنگ کو مؤثر طریقے سے استعمال کرنے کے لیے درکار کم از کم ضمانتیں فراہم کرتی ہیں۔

  1. سیکیورٹی پراپرٹی: باہمی اخراج۔ کسی بھی وقت، صرف ایک کلائنٹ تالا پکڑ سکتا ہے۔
  2. دستیابی پراپرٹی A: کوئی تعطل نہیں ہے۔ بالآخر تالا حاصل کرنا ہمیشہ ممکن ہوتا ہے، چاہے وہ کلائنٹ جس نے وسائل کو لاک کیا ہو ناکام ہو جائے یا ڈسک کے کسی دوسرے حصے پر اتر جائے۔
  3. دستیابی پراپرٹی B: غلطی کی رواداری۔ جب تک Redis نوڈس کی اکثریت چل رہی ہے، کلائنٹ تالے حاصل کرنے اور جاری کرنے کے قابل ہیں۔

اس معاملے میں ناکامی کی بحالی پر مبنی عمل درآمد کیوں کافی نہیں ہے۔
یہ سمجھنے کے لیے کہ ہم کیا بہتر کرنے جا رہے ہیں، آئیے Redis پر مبنی زیادہ تر تقسیم شدہ لاکنگ لائبریریوں کے ساتھ موجودہ حالات کا تجزیہ کریں۔

Redis کا استعمال کرتے ہوئے وسائل کو مقفل کرنے کا آسان ترین طریقہ یہ ہے کہ مثال میں ایک کلید بنائی جائے۔ عام طور پر، ایک کلید محدود زندگی کے ساتھ بنائی جاتی ہے، یہ Redis میں فراہم کردہ ایکسپائر فیچر کا استعمال کرتے ہوئے حاصل کیا جاتا ہے، اس لیے جلد یا بدیر یہ کلید جاری کر دی جاتی ہے (ہماری فہرست میں پراپرٹی 2)۔ جب کلائنٹ کو وسائل جاری کرنے کی ضرورت ہوتی ہے، تو یہ کلید کو حذف کر دیتا ہے۔

پہلی نظر میں، یہ حل کافی اچھا کام کرتا ہے، لیکن ایک مسئلہ ہے: ہمارا فن تعمیر ناکامی کا ایک نقطہ پیدا کرتا ہے۔ اگر میزبان Redis مثال ناکام ہو جائے تو کیا ہوتا ہے؟ چلو پھر ایک غلام شامل کریں! اور اگر پیش کنندہ دستیاب نہ ہو تو ہم اسے استعمال کریں گے۔ بدقسمتی سے، یہ اختیار قابل عمل نہیں ہے. ایسا کرنے سے، ہم باہمی اخراج کی خاصیت کو درست طریقے سے لاگو نہیں کر پائیں گے جس کی ہمیں حفاظت کو یقینی بنانے کی ضرورت ہے، کیونکہ Redis میں نقل کرنا غیر مطابقت پذیر ہے۔

ظاہر ہے، اس طرح کے ماڈل میں ریس کی حالت ہوتی ہے:

  1. کلائنٹ A ماسٹر پر ایک لاک حاصل کرتا ہے۔
  2. کلیدی اندراج غلام کو منتقل ہونے سے پہلے آقا ناکام ہو جاتا ہے۔
  3. پیروکار کو لیڈر بنا دیا جاتا ہے۔
  4. کلائنٹ B اسی وسیلہ پر ایک لاک حاصل کرتا ہے جسے A نے پہلے ہی لاک کیا ہوا ہے۔ سیکورٹی کی خلاف ورزی!

بعض اوقات یہ مکمل طور پر معمول کی بات ہے کہ خاص حالات میں، جیسے کہ ناکامی، بہت سے کلائنٹس ایک ہی وقت میں تالا کو پکڑ سکتے ہیں۔ ایسے معاملات میں، نقل پر مبنی حل کا اطلاق کیا جا سکتا ہے۔ دوسری صورت میں، ہم اس مضمون میں بیان کردہ حل کی سفارش کرتے ہیں.

ایک مثال کے ساتھ درست نفاذ

اوپر بیان کردہ سنگل انسٹینس کنفیگریشن کی کوتاہیوں پر قابو پانے کی کوشش کرنے سے پہلے، آئیے سمجھیں کہ اس سادہ معاملے کو کس طرح ٹھیک طریقے سے ہینڈل کیا جائے، کیونکہ یہ حل درحقیقت ان ایپلی کیشنز میں درست ہے جہاں وقتاً فوقتاً ریس کی شرط قابل قبول ہوتی ہے، اور اس لیے بھی کہ بلاکنگ واحد مثال اس بنیاد کے طور پر کام کرتا ہے جو یہاں بیان کردہ تقسیم شدہ الگورتھم میں استعمال ہوتا ہے۔

تالا حاصل کرنے کے لیے، یہ کریں:

SET resource_name my_random_value NX PX 30000

یہ کمانڈ صرف اس صورت میں ایک کلید کو انسٹال کرتی ہے جب یہ پہلے سے موجود نہ ہو (NX آپشن)، جس کی میعاد 30000 ملی سیکنڈز (PX آپشن) ہو۔ کلید پر سیٹ ہے "myrandomvalue" یہ قدر تمام کلائنٹس اور تمام لاک درخواستوں میں منفرد ہونی چاہیے۔
بنیادی طور پر، ایک بے ترتیب قدر کا استعمال لاک کو محفوظ طریقے سے جاری کرنے کے لیے کیا جاتا ہے، جس میں ایک اسکرپٹ Redis کو بتاتا ہے: کلید کو صرف اس صورت میں ہٹائیں جب یہ موجود ہو اور اس میں ذخیرہ شدہ قدر بالکل وہی ہے جس کی توقع تھی۔ یہ درج ذیل Lua اسکرپٹ کا استعمال کرتے ہوئے حاصل کیا جاتا ہے:

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

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

یہ بے ترتیب تار کیا ہونا چاہیے؟ میں اندازہ لگا رہا ہوں کہ یہ /dev/urandom سے 20 بائٹس ہونا چاہئے، لیکن آپ تار کو اپنے مقاصد کے لیے کافی منفرد بنانے کے لیے کم مہنگے طریقے تلاش کر سکتے ہیں۔ مثال کے طور پر، RC4 کو /dev/urandom کے ساتھ سیڈ کرنا اور پھر اس سے ایک چھدم بے ترتیب سٹریم بنانا ٹھیک ہوگا۔ ایک آسان حل میں مائیکرو سیکنڈ ریزولوشن کے علاوہ کلائنٹ آئی ڈی میں یونکس ٹائم کا مجموعہ شامل ہے۔ یہ اتنا محفوظ نہیں ہے، لیکن یہ شاید زیادہ تر سیاق و سباق میں کام پر منحصر ہے۔

جس وقت کو ہم کلید کی زندگی بھر کے پیمانہ کے طور پر استعمال کرتے ہیں اسے "لاک لائف ٹائم" کہا جاتا ہے۔ یہ قدر دونوں ہی وقت کی مقدار ہے جو لاک کے خود بخود جاری ہونے سے پہلے ہے اور اس سے پہلے کہ ایک کلائنٹ کو ایک آپریشن مکمل کرنے میں وقت ہوتا ہے اس سے پہلے کہ دوسرا کلائنٹ اس وسیلہ کو بند کر دے، درحقیقت باہمی اخراج کی ضمانتوں کی خلاف ورزی کیے بغیر۔ یہ گارنٹی صرف وقت کی ایک مخصوص ونڈو تک محدود ہے، جو اس وقت سے شروع ہوتی ہے جب تالا خریدا جاتا ہے۔

لہذا ہم نے تالا حاصل کرنے اور اسے جاری کرنے کے ایک اچھے طریقے پر تبادلہ خیال کیا ہے۔ سسٹم (اگر ہم ایک غیر تقسیم شدہ نظام کے بارے میں بات کر رہے ہیں جو ایک واحد اور ہمیشہ دستیاب مثال پر مشتمل ہے) محفوظ ہے۔ آئیے اس تصور کو تقسیم شدہ نظام تک بڑھاتے ہیں، جہاں ہمارے پاس ایسی کوئی ضمانت نہیں ہے۔

ریڈ لاک الگورتھم

الگورتھم کا تقسیم شدہ ورژن فرض کرتا ہے کہ ہمارے پاس N Redis ماسٹرز ہیں۔ یہ نوڈس ایک دوسرے سے مکمل طور پر آزاد ہیں، اس لیے ہم نقل یا کسی دوسرے مضمر کوآرڈینیشن سسٹم کا استعمال نہیں کرتے ہیں۔ ہم نے پہلے ہی اس بات کا احاطہ کیا ہے کہ کس طرح محفوظ طریقے سے ایک ہی موقع پر لاک حاصل کرنا اور اسے جاری کرنا ہے۔ ہم یہ سمجھتے ہیں کہ الگورتھم، جب کسی ایک مثال کے ساتھ کام کرتا ہے، بالکل اسی طریقہ کو استعمال کرے گا۔ اپنی مثالوں میں ہم N کو 5 پر سیٹ کرتے ہیں، جو کہ ایک معقول قدر ہے۔ اس طرح، ہمیں مختلف کمپیوٹرز یا ورچوئل مشینوں پر 5 ریڈیس ماسٹرز استعمال کرنے کی ضرورت ہوگی تاکہ یہ یقینی بنایا جا سکے کہ وہ ایک دوسرے سے بڑی حد تک آزادانہ طور پر کام کرتے ہیں۔

ایک تالا حاصل کرنے کے لیے، کلائنٹ مندرجہ ذیل کام انجام دیتا ہے:

  1. موجودہ وقت کو ملی سیکنڈ میں حاصل کرتا ہے۔
  2. ترتیب وار تمام N مثالوں پر ایک ہی کلیدی نام اور بے ترتیب اقدار کا استعمال کرتے ہوئے ایک تالا حاصل کرنے کی کوشش کرتا ہے۔ اسٹیج 2 میں، جب کلائنٹ فی مثال کی بنیاد پر ایک لاک سیٹ کرتا ہے، کلائنٹ اسے حاصل کرنے میں تاخیر کا استعمال کرتا ہے جو اس وقت کے مقابلے میں کافی کم ہوتا ہے جس کے بعد لاک خود بخود جاری ہوتا ہے۔ مثال کے طور پر، اگر بلاک کرنے کا دورانیہ 10 سیکنڈ ہے، تو تاخیر ~5-50 ملی سیکنڈز کی حد میں ہو سکتی ہے۔ یہ اس صورتحال کو ختم کرتا ہے جس میں کلائنٹ ایک ناکام ریڈیس نوڈ تک پہنچنے کی کوشش میں طویل عرصے تک بلاک رہ سکتا ہے: اگر مثال دستیاب نہیں ہے، تو ہم جلد از جلد کسی اور مثال سے رابطہ قائم کرنے کی کوشش کرتے ہیں۔
  3. تالا لینے کے لیے، کلائنٹ حساب لگاتا ہے کہ کتنا وقت گزر چکا ہے۔ ایسا کرنے کے لیے، یہ اصل وقت کی قیمت سے اس ٹائم اسٹیمپ کو گھٹا دیتا ہے جو مرحلہ 1 میں حاصل کیا گیا تھا۔ اگر اور صرف اس صورت میں جب کلائنٹ زیادہ تر مثالوں (کم از کم 3) پر لاک حاصل کرنے کے قابل ہو، اور اس میں لگنے والا کل وقت تالا حاصل کریں، تالے کی مدت سے کم، تالا کو حاصل کیا گیا سمجھا جاتا ہے۔
  4. اگر ایک لاک حاصل کر لیا گیا ہے، تو لاک کی مدت کو اصل لاک دورانیہ کے طور پر لیا جاتا ہے جو کہ مرحلہ 3 میں شمار کیے گئے گزرے ہوئے وقت کو کم کرتے ہیں۔
  5. اگر کلائنٹ کسی وجہ سے لاک حاصل کرنے میں ناکام رہتا ہے (یا تو وہ N/2+1 مثالوں کو لاک کرنے سے قاصر تھا، یا لاک کا دورانیہ منفی تھا)، تو وہ تمام مثالوں کو غیر مقفل کرنے کی کوشش کرے گا (یہاں تک کہ وہ بھی جو اس نے سوچا تھا کہ اسے بلاک نہیں کیا جا سکتا۔ )۔

کیا الگورتھم متضاد ہے؟

یہ الگورتھم اس مفروضے پر مبنی ہے کہ اگرچہ کوئی مطابقت پذیر گھڑی نہیں ہے جس پر تمام عمل کام کریں گے، لیکن ہر عمل میں مقامی وقت اب بھی تقریباً ایک ہی رفتار سے بہتا ہے، اور خرابی اس کل وقت کے مقابلے میں چھوٹی ہے جس کے بعد تالا لگا ہوا ہے۔ خود کار طریقے سے جاری. یہ مفروضہ عام کمپیوٹرز کے لیے عام صورت حال سے بہت ملتا جلتا ہے: ہر کمپیوٹر کی ایک مقامی گھڑی ہوتی ہے، اور ہم عام طور پر اس حقیقت پر اعتماد کر سکتے ہیں کہ مختلف کمپیوٹرز کے درمیان وقت کا فرق کم ہے۔

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

مندرجہ ذیل دلچسپ مضمون ایسے نظاموں کے بارے میں مزید بتاتا ہے جن کے لیے وقت کے وقفوں کی ہم آہنگی کی ضرورت ہوتی ہے۔ لیز: تقسیم شدہ فائل کیشے کی مستقل مزاجی کے لیے ایک موثر غلطی برداشت کرنے والا طریقہ کار.

ناکامی پر دوبارہ کوشش کریں۔

جب کوئی کلائنٹ لاک حاصل کرنے میں ناکام ہو جاتا ہے، تو اسے بے ترتیب تاخیر کے بعد دوبارہ کوشش کرنی چاہیے۔ یہ ایک ہی وقت میں ایک ہی وسائل پر تالا حاصل کرنے کی کوشش کرنے والے متعدد کلائنٹس کو ڈی سنکرونائز کرنے کے لیے کیا جاتا ہے (جو "اسپلٹ برین" کی صورت حال کا باعث بن سکتا ہے جس میں کوئی فاتح نہیں ہوتا ہے)۔ مزید برآں، ایک کلائنٹ جتنی تیزی سے Redis کی اکثریت پر تالا حاصل کرنے کی کوشش کرتا ہے، ونڈو اتنی ہی تنگ ہوتی ہے جس میں اسپلٹ برین کی صورت حال ہوسکتی ہے (اور دوبارہ کوششوں کی ضرورت اتنی ہی کم ہوگی)۔ لہذا، مثالی طور پر، کلائنٹ کو ملٹی پلیکسنگ کا استعمال کرتے ہوئے بیک وقت N مثالوں پر SET کمانڈ بھیجنے کی کوشش کرنی چاہیے۔

یہاں اس بات پر زور دینا ضروری ہے کہ جو کلائنٹس زیادہ تر تالے حاصل کرنے میں ناکام رہتے ہیں ان کے لیے (جزوی طور پر) حاصل کیے گئے تالے کو جاری کرنا کتنا ضروری ہے، تاکہ وسائل پر موجود تالے کو دوبارہ حاصل کرنے سے پہلے انہیں چابی کے ختم ہونے کا انتظار نہ کرنا پڑے۔ (حالانکہ اگر نیٹ ورک فریگمنٹیشن ہوتا ہے، اور کلائنٹ Redis مثالوں سے رابطہ کھو دیتا ہے، تو آپ کو کلید کے ختم ہونے کا انتظار کرتے ہوئے دستیابی جرمانہ ادا کرنا ہوگا)۔

تالہ جاری کریں۔

لاک کو جاری کرنا ایک سادہ آپریشن ہے جس کے لیے تمام مثالوں کو کھولنے کی ضرورت ہوتی ہے، قطع نظر اس سے کہ کلائنٹ نے کسی خاص مثال کو کامیابی کے ساتھ لاک کر دیا ہے۔

سیکورٹی کے تحفظات

کیا الگورتھم محفوظ ہے؟ آئیے تصور کرنے کی کوشش کریں کہ مختلف منظرناموں میں کیا ہوتا ہے۔

شروع کرنے کے لیے، آئیے فرض کریں کہ کلائنٹ زیادہ تر مثالوں پر لاک حاصل کرنے کے قابل تھا۔ ہر مثال میں ایک کلید ہوگی جس میں سب کے لیے یکساں زندگی ہوگی۔ تاہم، ان میں سے ہر ایک کی ایک مختلف وقت پر انسٹال کی گئی تھی، اس لیے ان کی میعاد مختلف اوقات میں ختم ہو جائے گی۔ لیکن، اگر پہلی کلید T1 (وہ وقت جسے ہم پہلے سرور سے رابطہ کرنے سے پہلے منتخب کرتے ہیں) سے بدتر وقت میں انسٹال کیا گیا تھا، اور آخری کلید T2 (جس وقت جواب موصول ہوا تھا) سے بدتر وقت پر انسٹال کیا گیا تھا۔ آخری سرور سے)، پھر ہمیں یقین ہے کہ سیٹ کی پہلی کلید جس کی میعاد ختم ہو جائے گی کم از کم زندہ رہے گی۔ MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT. باقی تمام چابیاں بعد میں ختم ہو جائیں گی، اس لیے ہم اس بات کا یقین کر سکتے ہیں کہ کم از کم اس وقت کے لیے تمام کیز بیک وقت درست ہوں گی۔

اس وقت کے دوران جب زیادہ تر چابیاں درست رہیں، دوسرا کلائنٹ لاک حاصل کرنے کے قابل نہیں ہو گا، کیونکہ N/2+1 SET NX آپریشنز کامیاب نہیں ہو سکتے اگر N/2+1 کیز پہلے سے موجود ہوں۔ اس لیے، ایک بار لاک حاصل کر لینے کے بعد، اسی لمحے اسے دوبارہ حاصل کرنا ناممکن ہے (اس سے باہمی اخراج کی جائیداد کی خلاف ورزی ہوگی)۔
تاہم، ہم اس بات کو یقینی بنانا چاہتے ہیں کہ ایک ہی وقت میں ایک لاک حاصل کرنے کی کوشش کرنے والے متعدد کلائنٹس ایک ہی وقت میں کامیاب نہیں ہوسکتے ہیں۔

اگر کلائنٹ نے زیادہ سے زیادہ مثالوں کو لاک کی زیادہ سے زیادہ مدت کے بارے میں یا اس سے زیادہ کے لیے مقفل کر دیا ہے، تو وہ تالا کو غلط سمجھے گا اور مثالوں کو غیر مقفل کر دے گا۔ لہذا، ہمیں صرف اس معاملے کو مدنظر رکھنا ہے جس میں کلائنٹ نے میعاد ختم ہونے کی تاریخ سے کم وقت میں زیادہ تر مثالوں کو بلاک کرنے کا انتظام کیا ہے۔ اس صورت میں، اس وقت کے دوران، مندرجہ بالا دلیل کے بارے میں MIN_VALIDITY کسی بھی کلائنٹ کو تالے کو دوبارہ حاصل کرنے کے قابل نہیں ہونا چاہئے۔ لہذا، بہت سے کلائنٹس N/2+1 مثالوں کو ایک ہی وقت میں لاک کر سکیں گے (جو کہ مرحلہ 2 کے اختتام پر ختم ہوتا ہے) صرف اس صورت میں جب اکثریت کو لاک کرنے کا وقت TTL وقت سے زیادہ ہو، جو لاک کو غلط قرار دیتا ہے۔

کیا آپ سیکورٹی کا باضابطہ ثبوت فراہم کر سکتے ہیں، موجودہ ملتے جلتے الگورتھم کی نشاندہی کر سکتے ہیں، یا اوپر میں کوئی بگ ڈھونڈ سکتے ہیں؟

قابل رسائی تحفظات

سسٹم کی دستیابی تین اہم خصوصیات پر منحصر ہے:

  1. خودکار طور پر تالے جاری کریں (کیوں کی میعاد ختم ہونے کے بعد): چابیاں آخر کار تالے کے لیے استعمال ہونے کے لیے دوبارہ دستیاب ہوں گی۔
  2. حقیقت یہ ہے کہ کلائنٹ عام طور پر تالے کو ہٹا کر ایک دوسرے کی مدد کرتے ہیں جب مطلوبہ تالا حاصل نہیں کیا گیا ہے، یا حاصل کیا گیا ہے اور کام مکمل ہو چکا ہے؛ لہذا امکان ہے کہ ہمیں تالا دوبارہ حاصل کرنے کے لیے چابیاں ختم ہونے کا انتظار نہیں کرنا پڑے گا۔
  3. حقیقت یہ ہے کہ جب ایک کلائنٹ کو تالا حاصل کرنے کے لیے دوبارہ کوشش کرنے کی ضرورت ہوتی ہے، تو وہ زیادہ تر تالے حاصل کرنے کے لیے درکار مدت سے نسبتاً زیادہ وقت کا انتظار کرتا ہے۔ اس سے وسائل کے لیے مسابقت کے دوران پیدا ہونے والی دماغی تقسیم کے امکانات کم ہو جاتے ہیں۔

تاہم، نیٹ ورک سیگمنٹس کے TTL کے برابر دستیابی کا جرمانہ ہے، لہذا اگر ملحقہ سیگمنٹس ہیں، تو جرمانہ غیر معینہ مدت کے لیے ہو سکتا ہے۔ یہ اس وقت ہوتا ہے جب بھی کوئی کلائنٹ لاک حاصل کرتا ہے اور پھر اسے جاری کرنے سے پہلے کسی دوسرے طبقے کو چیر دیتا ہے۔

اصولی طور پر، لامحدود متصل نیٹ ورک سیگمنٹس کے پیش نظر، ایک نظام لامحدود مدت تک دستیاب نہیں رہ سکتا ہے۔

کارکردگی، فیل اوور اور fsync

بہت سے لوگ Redis استعمال کرتے ہیں کیونکہ انہیں لاک سرور کی اعلی کارکردگی کی ضرورت ہوتی ہے تالے حاصل کرنے اور جاری کرنے کے لیے درکار تاخیر کے لحاظ سے، اور حصول/ریلیز کی تعداد جو فی سیکنڈ مکمل ہو سکتی ہے۔ اس ضرورت کو پورا کرنے کے لیے، تاخیر کو کم کرنے کے لیے N Redis سرورز کے ساتھ بات چیت کرنے کی حکمت عملی ہے۔ یہ ایک ملٹی پلیکسنگ حکمت عملی ہے (یا "غریب آدمی کی ملٹی پلیکسنگ"، جہاں ساکٹ کو نان بلاکنگ موڈ میں رکھا جاتا ہے، تمام کمانڈز بھیجتا ہے، اور کمانڈز کو بعد میں پڑھتا ہے، یہ فرض کرتے ہوئے کہ کلائنٹ اور ہر مثال کے درمیان راؤنڈ ٹرپ کا وقت یکساں ہے) .

تاہم، اگر ہم ناکامیوں سے قابل اعتماد بحالی کے ساتھ ایک ماڈل بنانے کی کوشش کرتے ہیں تو ہمیں طویل مدتی ڈیٹا اسٹوریج سے وابستہ غور و فکر کو بھی مدنظر رکھنا ہوگا۔

بنیادی طور پر، مسئلہ کو واضح کرنے کے لیے، آئیے فرض کریں کہ ہم Redis کو بغیر کسی طویل مدتی ڈیٹا اسٹوریج کے کنفیگر کرتے ہیں۔ کلائنٹ 3 میں سے 5 کو بلاک کرنے کا انتظام کرتا ہے۔ ان مثالوں میں سے ایک جسے کلائنٹ نے بلاک کرنے میں کامیاب کیا تھا، اور اس وقت اسی وسیلہ کے لیے دوبارہ 3 مثالیں ہیں، جنہیں ہم بلاک کر سکتے ہیں، اور ایک اور کلائنٹ، اس کے نتیجے میں، دوبارہ شروع ہونے والی مثال کو بلاک کر سکتا ہے، جو کہ سیکیورٹی پراپرٹی کی خلاف ورزی کرتا ہے۔ تالے کی خصوصیت کو فرض کرتا ہے۔

اگر آپ ڈیٹا آگے (AOF) کو فعال کرتے ہیں، تو صورتحال قدرے بہتر ہوگی۔ مثال کے طور پر، آپ SHUTDOWN کمانڈ بھیج کر اور اسے دوبارہ شروع کر کے سرور کو فروغ دے سکتے ہیں۔ چونکہ Redis میں میعاد ختم ہونے کی کارروائیوں کو اس طرح سے لاگو کیا جاتا ہے کہ سرور کے بند ہونے پر بھی وقت گزرتا رہتا ہے، ہماری تمام ضروریات ٹھیک ہیں۔ یہ معمول ہے جب تک کہ ایک عام شٹ ڈاؤن کو یقینی بنایا جائے۔ بجلی بند ہونے کی صورت میں کیا کریں؟ اگر Redis کو بطور ڈیفالٹ ترتیب دیا گیا ہے، fsync ہر سیکنڈ میں ڈسک پر ہم آہنگی کے ساتھ، تو یہ ممکن ہے کہ دوبارہ شروع کرنے کے بعد ہمارے پاس ہماری کلید نہ ہو۔ نظریاتی طور پر، اگر ہم کسی بھی مثال کے دوبارہ شروع ہونے کے دوران لاک سیکیورٹی کی ضمانت دینا چاہتے ہیں، تو ہمیں فعال کرنا چاہیے۔ fsync=always طویل مدتی ڈیٹا اسٹوریج کی ترتیبات میں۔ یہ کارکردگی کو مکمل طور پر ختم کر دے گا، CP سسٹمز کی سطح تک جو روایتی طور پر تقسیم شدہ تالے کو محفوظ طریقے سے نافذ کرنے کے لیے استعمال ہوتے ہیں۔

لیکن صورتحال اس سے بہتر ہے جو پہلی نظر میں نظر آتی ہے۔ اصولی طور پر، الگورتھم کی حفاظت محفوظ ہے کیونکہ جب ایک ناکامی کے بعد مثال کو دوبارہ شروع کیا جاتا ہے، تو یہ اب کسی ایسے لاک میں حصہ نہیں لے رہا ہے جو فی الحال فعال ہے۔

اس کو یقینی بنانے کے لیے، ہمیں صرف اس بات کو یقینی بنانا ہوگا کہ ناکامی کے بعد مثال ہمارے استعمال کردہ زیادہ سے زیادہ TTL سے قدرے زیادہ وقت کے لیے دستیاب نہیں ہے۔ اس طرح ہم میعاد ختم ہونے کی تاریخ تک انتظار کریں گے اور ان تمام کلیدوں کے خودکار ریلیز کا انتظار کریں گے جو ناکامی کے وقت فعال تھیں۔

تاخیر سے دوبارہ شروع ہونے کا استعمال کرتے ہوئے، اصولی طور پر Redis میں طویل مدتی استقامت کی عدم موجودگی میں بھی سیکورٹی حاصل کرنا ممکن ہے۔ تاہم، نوٹ کریں کہ اس کے نتیجے میں رسائی کی خلاف ورزی پر جرمانہ ہو سکتا ہے۔ مثال کے طور پر، اگر زیادہ تر مثالیں ناکام ہو جاتی ہیں، تو نظام TTL کے لیے عالمی سطح پر غیر دستیاب ہو جائے گا (اور اس دوران کوئی وسیلہ بلاک نہیں کیا جا سکتا)۔

ہم الگورتھم کی دستیابی میں اضافہ کرتے ہیں: ہم بلاکنگ کو بڑھاتے ہیں۔

اگر کلائنٹس کی طرف سے انجام دیا جانے والا کام چھوٹے مراحل پر مشتمل ہے، تو یہ ممکن ہے کہ پہلے سے طے شدہ لاک کی مدت کو کم کیا جائے اور تالے کو بڑھانے کے لیے ایک طریقہ کار کو نافذ کیا جائے۔ اصولی طور پر، اگر کلائنٹ کمپیوٹنگ میں مصروف ہے اور لاک کی میعاد ختم ہونے کی قدر خطرناک حد تک کم ہے، تو آپ Lua اسکرپٹ کو ان تمام مثالوں میں بھیج سکتے ہیں جو کلید کے TTL کو بڑھاتی ہے اگر کلید اب بھی موجود ہے اور اس کی قیمت اب بھی ایک بے ترتیب قدر ہے جب حاصل کی جاتی ہے۔ تالا حاصل کیا گیا تھا.

ایک کلائنٹ کو صرف اس صورت میں دوبارہ حاصل کرنے پر غور کرنا چاہیے کہ جب اس نے میعاد کی مدت کے اندر زیادہ تر مثالوں کو لاک کرنے کا انتظام کیا ہو۔

درست ہے، تکنیکی طور پر الگورتھم تبدیل نہیں ہوتا ہے، اس لیے تالے حاصل کرنے کے لیے بار بار کوششوں کی زیادہ سے زیادہ تعداد محدود ہونی چاہیے، ورنہ قابل رسائی خصوصیات کی خلاف ورزی کی جائے گی۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں