HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

بڑے ڈیٹا کے ساتھ کام کرتے وقت اعلی کارکردگی کلیدی ضروریات میں سے ایک ہے۔ Sberbank کے ڈیٹا لوڈنگ ڈیپارٹمنٹ میں، ہم تقریباً تمام لین دین کو اپنے Hadoop پر مبنی ڈیٹا کلاؤڈ میں ڈالتے ہیں اور اس وجہ سے معلومات کے واقعی بڑے بہاؤ سے نمٹتے ہیں۔ فطری طور پر، ہم ہمیشہ کارکردگی کو بہتر بنانے کے طریقے تلاش کرتے رہتے ہیں، اور اب ہم آپ کو بتانا چاہتے ہیں کہ ہم نے کس طرح RegionServer HBase اور HDFS کلائنٹ کو پیچ کرنے کا انتظام کیا، جس کی بدولت ہم پڑھنے کی کارروائیوں کی رفتار کو نمایاں طور پر بڑھانے میں کامیاب ہوئے۔
HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

تاہم، بہتری کے نچوڑ پر جانے سے پہلے، یہ پابندیوں کے بارے میں بات کرنے کے قابل ہے، جو اصولی طور پر، اگر آپ ایچ ڈی ڈی پر بیٹھتے ہیں تو ان کا مقابلہ نہیں کیا جا سکتا۔

HDD اور تیز رینڈم ایکسیس ریڈز کیوں مطابقت نہیں رکھتے
جیسا کہ آپ جانتے ہیں، HBase، اور بہت سے دوسرے ڈیٹا بیس، ڈیٹا کو کئی دسیوں کلو بائٹ سائز کے بلاکس میں محفوظ کرتے ہیں۔ پہلے سے طے شدہ طور پر یہ تقریباً 64 KB ہے۔ اب تصور کریں کہ ہمیں صرف 100 بائٹس حاصل کرنے کی ضرورت ہے اور ہم HBase سے کہتے ہیں کہ وہ ایک مخصوص کلید کا استعمال کرتے ہوئے ہمیں یہ ڈیٹا فراہم کرے۔ چونکہ HFiles میں بلاک کا سائز 64 KB ہے، اس لیے درخواست ضرورت سے 640 گنا زیادہ (صرف ایک منٹ!) ہوگی۔

اگلا، چونکہ درخواست HDFS اور اس کے میٹا ڈیٹا کیشنگ میکانزم سے گزرے گی۔ شارٹ سرکٹ کیچ (جو فائلوں تک براہ راست رسائی کی اجازت دیتا ہے)، یہ ڈسک سے پہلے ہی 1 MB پڑھنے کی طرف جاتا ہے۔ تاہم، یہ پیرامیٹر کے ساتھ ایڈجسٹ کیا جا سکتا ہے dfs.client.read.shortcircuit.buffer.size اور بہت سے معاملات میں اس قدر کو کم کرنا سمجھ میں آتا ہے، مثال کے طور پر 126 KB تک۔

ہم کہتے ہیں کہ ہم یہ کرتے ہیں، لیکن اس کے علاوہ، جب ہم java api کے ذریعے ڈیٹا پڑھنا شروع کرتے ہیں، جیسے کہ FileChannel.read جیسے فنکشنز اور آپریٹنگ سسٹم سے ڈیٹا کی مخصوص مقدار کو پڑھنے کے لیے کہتے ہیں، تو یہ "صرف صورت میں" 2 گنا زیادہ پڑھتا ہے۔ ، یعنی ہمارے معاملے میں 256 KB۔ اس کی وجہ یہ ہے کہ جاوا کے پاس اس رویے کو روکنے کے لیے FADV_RANDOM پرچم سیٹ کرنے کا آسان طریقہ نہیں ہے۔

نتیجے کے طور پر، ہمارے 100 بائٹس حاصل کرنے کے لیے، ہڈ کے نیچے 2600 گنا زیادہ پڑھا جاتا ہے۔ ایسا لگتا ہے کہ حل واضح ہے، آئیے بلاک کے سائز کو ایک کلو بائٹ تک کم کریں، ذکر کردہ جھنڈا سیٹ کریں اور روشن خیالی کی زبردست سرعت حاصل کریں۔ لیکن مصیبت یہ ہے کہ بلاک کے سائز کو 2 گنا کم کر کے، ہم فی یونٹ پڑھنے والے بائٹس کی تعداد کو بھی 2 گنا کم کر دیتے ہیں۔

FADV_RANDOM پرچم کو ترتیب دینے سے کچھ فائدہ حاصل کیا جا سکتا ہے، لیکن صرف ہائی ملٹی تھریڈنگ اور 128 KB کے بلاک سائز کے ساتھ، لیکن یہ زیادہ سے زیادہ دسیوں فیصد ہے:

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

ٹیسٹ 100 فائلوں پر کیے گئے، ہر ایک 1 GB سائز میں اور 10 HDDs پر واقع ہے۔

آئیے حساب لگائیں کہ ہم اصولی طور پر اس رفتار سے کیا کر سکتے ہیں:
ہم کہتے ہیں کہ ہم 10 ڈسکوں سے 280 ایم بی فی سیکنڈ کی رفتار سے پڑھتے ہیں، یعنی 3 ملین بار 100 بائٹس۔ لیکن جیسا کہ ہمیں یاد ہے، ہمیں جو ڈیٹا درکار ہے وہ پڑھے جانے والے ڈیٹا سے 2600 گنا کم ہے۔ اس طرح، ہم 3 ملین کو 2600 سے تقسیم کرتے ہیں اور حاصل کرتے ہیں۔ 1100 ریکارڈ فی سیکنڈ۔

افسردہ کرنے والا، ہے نا؟ یہ فطرت ہے۔ بے ترتیب رسائی HDD پر ڈیٹا تک رسائی - بلاک سائز سے قطع نظر۔ یہ بے ترتیب رسائی کی طبعی حد ہے اور کوئی ڈیٹا بیس اس طرح کے حالات میں مزید نچوڑ نہیں سکتا۔

پھر ڈیٹا بیس بہت زیادہ رفتار کیسے حاصل کرتے ہیں؟ اس سوال کا جواب دینے کے لیے، آئیے دیکھتے ہیں کہ مندرجہ ذیل تصویر میں کیا ہو رہا ہے۔

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

یہاں ہم دیکھتے ہیں کہ پہلے چند منٹوں کے لیے رفتار واقعی ایک ہزار ریکارڈ فی سیکنڈ ہے۔ تاہم، مزید، اس حقیقت کی وجہ سے کہ درخواست کی گئی تھی اس سے کہیں زیادہ پڑھا جاتا ہے، ڈیٹا آپریٹنگ سسٹم (لینکس) کے بف/کیشے میں ختم ہو جاتا ہے اور رفتار 60 ہزار فی سیکنڈ تک بڑھ جاتی ہے۔

اس طرح، مزید ہم صرف اس ڈیٹا تک رسائی کو تیز کرنے سے نمٹیں گے جو OS کیشے میں ہے یا SSD/NVMe اسٹوریج ڈیوائسز میں موجود ہے جس کی رسائی کی رفتار کا موازنہ ہے۔

ہمارے معاملے میں، ہم 4 سرورز کے بنچ پر ٹیسٹ کریں گے، جن میں سے ہر ایک کو مندرجہ ذیل چارج کیا جاتا ہے:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 تھریڈز۔
میموری: 730 جی بی۔
جاوا ورژن: 1.8.0_111

اور یہاں اہم نکتہ میزوں میں ڈیٹا کی مقدار ہے جسے پڑھنے کی ضرورت ہے۔ حقیقت یہ ہے کہ اگر آپ کسی ایسے ٹیبل سے ڈیٹا پڑھتے ہیں جو مکمل طور پر HBase کیش میں رکھا گیا ہے، تو یہ آپریٹنگ سسٹم کے بف/کیشے سے پڑھنے میں بھی نہیں آئے گا۔ کیونکہ HBase بطور ڈیفالٹ 40% میموری کو بلاک کیچ نامی ڈھانچے میں مختص کرتا ہے۔ بنیادی طور پر یہ ایک ConcurrentHashMap ہے، جہاں کلید فائل کا نام + بلاک کا آفسیٹ ہے، اور قیمت اس آفسیٹ میں اصل ڈیٹا ہے۔

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

مثال کے طور پر، ہمارے معاملے میں، ایک RS پر BlockCache کا حجم تقریباً 12 GB ہے۔ ہم نے ایک نوڈ پر دو RS اتارے، یعنی تمام نوڈس پر بلاک کیچ کے لیے 96 جی بی مختص کیے گئے ہیں۔ اور اس سے کئی گنا زیادہ ڈیٹا ہے، مثال کے طور پر، اسے 4 ٹیبلز ہونے دیں، ہر ایک میں 130 ریجنز ہوں، جس میں فائلیں 800 MB سائز کی ہوں، FAST_DIFF کے ذریعے کمپریس کی گئی ہوں، یعنی کل 410 جی بی (یہ خالص ڈیٹا ہے، یعنی نقل کے عنصر کو مدنظر رکھے بغیر)۔

اس طرح، BlockCache ڈیٹا کے کل حجم کا صرف 23% ہے اور یہ بگ ڈیٹا کہلانے والے حقیقی حالات کے بہت قریب ہے۔ اور یہیں سے مزہ شروع ہوتا ہے - کیونکہ ظاہر ہے، جتنے کم کیش ہٹ ہوں گے، کارکردگی اتنی ہی خراب ہوگی۔ سب کے بعد، اگر آپ یاد کرتے ہیں، تو آپ کو بہت زیادہ کام کرنا پڑے گا - یعنی کالنگ سسٹم کے افعال پر نیچے جائیں۔ تاہم، اس سے گریز نہیں کیا جا سکتا، تو آئیے ایک بالکل مختلف پہلو پر نظر ڈالتے ہیں - کیش کے اندر موجود ڈیٹا کا کیا ہوتا ہے؟

آئیے صورتحال کو آسان بنائیں اور فرض کریں کہ ہمارے پاس ایک کیش ہے جو صرف 1 آبجیکٹ پر فٹ بیٹھتا ہے۔ یہاں اس کی ایک مثال ہے کہ جب ہم کیش سے 3 گنا بڑے ڈیٹا والیوم کے ساتھ کام کرنے کی کوشش کریں گے تو کیا ہوگا، ہمیں یہ کرنا پڑے گا:

1. بلاک 1 کو کیشے میں رکھیں
2. کیشے سے بلاک 1 کو ہٹا دیں۔
3. بلاک 2 کو کیشے میں رکھیں
4. کیشے سے بلاک 2 کو ہٹا دیں۔
5. بلاک 3 کو کیشے میں رکھیں

5 کارروائیاں مکمل! تاہم، اس صورتحال کو نارمل نہیں کہا جا سکتا؛ درحقیقت، ہم HBase کو مکمل طور پر بیکار کام کرنے پر مجبور کر رہے ہیں۔ یہ OS کیشے سے ڈیٹا کو مسلسل پڑھتا ہے، اسے BlockCache میں رکھتا ہے، صرف اسے تقریباً فوراً باہر پھینکنے کے لیے کیونکہ ڈیٹا کا ایک نیا حصہ آ چکا ہے۔ پوسٹ کے آغاز میں اینیمیشن مسئلہ کا جوہر دکھاتی ہے - کوڑا اٹھانے والا بڑے پیمانے پر جا رہا ہے، ماحول گرم ہو رہا ہے، دور دراز اور گرم سویڈن میں چھوٹی گریٹا پریشان ہو رہی ہے۔ اور ہم IT لوگوں کو واقعی یہ پسند نہیں ہے جب بچے اداس ہوتے ہیں، اس لیے ہم سوچنا شروع کر دیتے ہیں کہ ہم اس کے بارے میں کیا کر سکتے ہیں۔

کیا ہوگا اگر آپ تمام بلاکس کو کیشے میں نہیں بلکہ ان میں سے صرف ایک خاص فیصد ڈالتے ہیں، تاکہ کیش اوور فلو نہ ہو؟ آئیے BlockCache میں ڈیٹا ڈالنے کے لیے فنکشن کے آغاز میں کوڈ کی صرف چند لائنیں شامل کرکے شروع کریں:

  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {
    if (cacheDataBlockPercent != 100 && buf.getBlockType().isData()) {
      if (cacheKey.getOffset() % 100 >= cacheDataBlockPercent) {
        return;
      }
    }
...

یہاں نکتہ درج ذیل ہے: آفسیٹ فائل میں بلاک کی پوزیشن ہے اور اس کے آخری ہندسوں کو بے ترتیب اور یکساں طور پر 00 سے 99 تک تقسیم کیا گیا ہے۔ اس لیے، ہم صرف ان کو چھوڑیں گے جو ہمیں درکار رینج میں آتے ہیں۔

مثال کے طور پر، cacheDataBlockPercent = 20 سیٹ کریں اور دیکھیں کہ کیا ہوتا ہے:

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

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

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

ایک ہی وقت میں، CPU کا استعمال بڑھتا ہے، لیکن پیداواری صلاحیت سے بہت کم ہے:

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

یہ بات بھی قابل غور ہے کہ بلاک کیچ میں محفوظ کردہ بلاکس مختلف ہیں۔ زیادہ تر، تقریباً 95٪، خود ڈیٹا ہے۔ اور باقی میٹا ڈیٹا ہے، جیسے بلوم فلٹرز یا LEAF_INDEX اور т.д.. یہ ڈیٹا کافی نہیں ہے، لیکن یہ بہت مفید ہے، کیونکہ ڈیٹا تک براہ راست رسائی سے پہلے، HBase یہ سمجھنے کے لیے میٹا کا رخ کرتا ہے کہ آیا یہاں مزید تلاش کرنا ضروری ہے اور، اگر ایسا ہے تو، دلچسپی کا بلاک بالکل کہاں واقع ہے۔

لہذا، کوڈ میں ہم چیک کنڈیشن دیکھتے ہیں۔ buf.getBlockType().isData() اور اس میٹا کا شکریہ، ہم اسے کسی بھی صورت میں کیشے میں چھوڑ دیں گے۔

اب ایک بار میں بوجھ کو بڑھاتے ہیں اور فیچر کو تھوڑا سا سخت کرتے ہیں۔ پہلے ٹیسٹ میں ہم نے کٹ آف فیصد = 20 بنایا اور BlockCache کو قدرے کم استعمال کیا گیا۔ اب آئیے اسے 23% پر سیٹ کرتے ہیں اور ہر 100 منٹ میں 5 تھریڈز شامل کرتے ہیں یہ دیکھنے کے لیے کہ کس مقام پر سنترپتی ہوتی ہے:

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

یہاں ہم دیکھتے ہیں کہ اصل ورژن تقریباً فی سیکنڈ تقریباً 100 ہزار درخواستوں کی حد تک پہنچ جاتا ہے۔ جبکہ پیچ 300 ہزار تک کی ایکسلریشن دیتا ہے۔ اسی وقت، یہ واضح ہے کہ مزید سرعت اب اتنی "آزاد" نہیں رہی؛ CPU کا استعمال بھی بڑھ رہا ہے۔

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

اس کو کنٹرول کرنے کے لیے تین آپشنز شامل کیے گئے ہیں:

hbase.lru.cache.heavy.eviction.count.limit - یہ سیٹ کرتا ہے کہ ہم آپٹیمائزیشن کا استعمال شروع کرنے سے پہلے کتنی بار کیش سے ڈیٹا نکالنے کا عمل چلنا چاہیے (یعنی بلاکس کو چھوڑنا)۔ پہلے سے طے شدہ طور پر یہ MAX_INT = 2147483647 کے برابر ہے اور درحقیقت اس کا مطلب ہے کہ فیچر اس قدر کے ساتھ کبھی کام کرنا شروع نہیں کرے گا۔ کیونکہ بے دخلی کا عمل ہر 5 - 10 سیکنڈ بعد شروع ہوتا ہے (یہ بوجھ پر منحصر ہے) اور 2147483647 * 10/60/60/24/365 = 680 سال۔ تاہم، ہم اس پیرامیٹر کو 0 پر سیٹ کر سکتے ہیں اور لانچ کے فوراً بعد فیچر کو کام کر سکتے ہیں۔

تاہم، اس پیرامیٹر میں ایک پے لوڈ بھی ہے۔ اگر ہمارا بوجھ ایسا ہے کہ قلیل مدتی پڑھنا (دن کے وقت کہتے ہیں) اور طویل مدتی پڑھنا (رات میں) مسلسل ایک دوسرے سے جڑے رہتے ہیں، تو ہم اس بات کو یقینی بنا سکتے ہیں کہ خصوصیت صرف اس وقت آن ہو جب طویل پڑھنے کی کارروائیاں جاری ہوں۔

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

hbase.lru.cache.heavy.eviction.mb.size.limit — سیٹ کرتا ہے کہ ہم 10 سیکنڈ میں کتنے میگا بائٹس کو کیشے میں رکھنا چاہتے ہیں (اور یقیناً بے دخل)۔ فیچر اس قدر تک پہنچنے اور اسے برقرار رکھنے کی کوشش کرے گا۔ نقطہ یہ ہے: اگر ہم گیگا بائٹس کو کیشے میں ڈالتے ہیں، تو ہمیں گیگا بائٹس کو نکالنا پڑے گا، اور یہ، جیسا کہ ہم نے اوپر دیکھا، بہت مہنگا ہے۔ تاہم، آپ کو اسے بہت چھوٹا سیٹ کرنے کی کوشش نہیں کرنی چاہیے، کیونکہ اس سے بلاک سکپ موڈ وقت سے پہلے باہر نکل جائے گا۔ طاقتور سرورز کے لیے (تقریباً 20-40 فزیکل کور)، یہ تقریباً 300-400 MB سیٹ کرنا بہتر ہے۔ متوسط ​​طبقے کے لیے (~10 کور) 200-300 MB۔ کمزور سسٹمز (2-5 کور) کے لیے 50-100 MB نارمل ہو سکتا ہے (ان پر ٹیسٹ نہیں کیا گیا)۔

آئیے دیکھتے ہیں کہ یہ کیسے کام کرتا ہے: آئیے کہتے ہیں کہ ہم نے hbase.lru.cache.heavy.eviction.mb.size.limit = 500 سیٹ کیا ہے، وہاں ایک قسم کا بوجھ (پڑھنا) ہے اور پھر ہر ~10 سیکنڈ میں ہم حساب لگاتے ہیں کہ کتنے بائٹس تھے۔ فارمولے کا استعمال کرتے ہوئے بے دخل کیا گیا:

اوور ہیڈ = فریڈ بائٹس سم (ایم بی) * 100 / حد (ایم بی) - 100؛

اگر حقیقت میں 2000 MB کو بے دخل کیا گیا تھا، تو اوور ہیڈ اس کے برابر ہے:

2000 * 100 / 500 - 100 = 300%

الگورتھم چند دسیوں فیصد سے زیادہ برقرار رکھنے کی کوشش کرتے ہیں، لہذا یہ خصوصیت کیشڈ بلاکس کی فیصد کو کم کر دے گی، اس طرح آٹو ٹیوننگ میکانزم کو نافذ کرے گا۔

تاہم، اگر لوڈ کم ہوتا ہے، تو مان لیں کہ صرف 200 MB کو بے دخل کیا گیا ہے اور اوور ہیڈ منفی ہو جاتا ہے (نام نہاد اوور شوٹنگ):

200 * 100 / 500 - 100 = -60%

اس کے برعکس، خصوصیت کیشڈ بلاکس کی فیصد میں اضافہ کرے گا جب تک کہ اوور ہیڈ مثبت نہ ہوجائے۔

ذیل میں ایک مثال ہے کہ یہ حقیقی ڈیٹا پر کیسا لگتا ہے۔ 0% تک پہنچنے کی کوشش کرنے کی ضرورت نہیں ہے، یہ ناممکن ہے۔ یہ بہت اچھا ہوتا ہے جب یہ تقریباً 30 - 100% ہوتا ہے، یہ مختصر مدت کے اضافے کے دوران اصلاح کے موڈ سے قبل از وقت نکلنے سے بچنے میں مدد کرتا ہے۔

hbase.lru.cache.heavy.eviction.overhead.coefficient - سیٹ کرتا ہے کہ ہم کتنی جلدی نتیجہ حاصل کرنا چاہیں گے۔ اگر ہم یقینی طور پر جانتے ہیں کہ ہماری پڑھائی زیادہ تر لمبی ہوتی ہے اور انتظار نہیں کرنا چاہتے تو ہم اس تناسب کو بڑھا سکتے ہیں اور تیزی سے اعلی کارکردگی حاصل کر سکتے ہیں۔

مثال کے طور پر، ہم نے یہ عدد = 0.01 مقرر کیا ہے۔ اس کا مطلب یہ ہے کہ اوور ہیڈ (اوپر دیکھیں) کو اس نمبر سے نتیجہ کے ساتھ ضرب دیا جائے گا اور کیشڈ بلاکس کا فیصد کم ہو جائے گا۔ آئیے فرض کریں کہ اوور ہیڈ = 300٪ اور گتانک = 0.01، پھر کیشڈ بلاکس کا فیصد 3٪ کم ہو جائے گا۔

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

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

نفاذ کوڈ

        LruBlockCache cache = this.cache.get();
        if (cache == null) {
          break;
        }
        freedSumMb += cache.evict()/1024/1024;
        /*
        * Sometimes we are reading more data than can fit into BlockCache
        * and it is the cause a high rate of evictions.
        * This in turn leads to heavy Garbage Collector works.
        * So a lot of blocks put into BlockCache but never read,
        * but spending a lot of CPU resources.
        * Here we will analyze how many bytes were freed and decide
        * decide whether the time has come to reduce amount of caching blocks.
        * It help avoid put too many blocks into BlockCache
        * when evict() works very active and save CPU for other jobs.
        * More delails: https://issues.apache.org/jira/browse/HBASE-23887
        */

        // First of all we have to control how much time
        // has passed since previuos evict() was launched
        // This is should be almost the same time (+/- 10s)
        // because we get comparable volumes of freed bytes each time.
        // 10s because this is default period to run evict() (see above this.wait)
        long stopTime = System.currentTimeMillis();
        if ((stopTime - startTime) > 1000 * 10 - 1) {
          // Here we have to calc what situation we have got.
          // We have the limit "hbase.lru.cache.heavy.eviction.bytes.size.limit"
          // and can calculte overhead on it.
          // We will use this information to decide,
          // how to change percent of caching blocks.
          freedDataOverheadPercent =
            (int) (freedSumMb * 100 / cache.heavyEvictionMbSizeLimit) - 100;
          if (freedSumMb > cache.heavyEvictionMbSizeLimit) {
            // Now we are in the situation when we are above the limit
            // But maybe we are going to ignore it because it will end quite soon
            heavyEvictionCount++;
            if (heavyEvictionCount > cache.heavyEvictionCountLimit) {
              // It is going for a long time and we have to reduce of caching
              // blocks now. So we calculate here how many blocks we want to skip.
              // It depends on:
             // 1. Overhead - if overhead is big we could more aggressive
              // reducing amount of caching blocks.
              // 2. How fast we want to get the result. If we know that our
              // heavy reading for a long time, we don't want to wait and can
              // increase the coefficient and get good performance quite soon.
              // But if we don't sure we can do it slowly and it could prevent
              // premature exit from this mode. So, when the coefficient is
              // higher we can get better performance when heavy reading is stable.
              // But when reading is changing we can adjust to it and set
              // the coefficient to lower value.
              int change =
                (int) (freedDataOverheadPercent * cache.heavyEvictionOverheadCoefficient);
              // But practice shows that 15% of reducing is quite enough.
              // We are not greedy (it could lead to premature exit).
              change = Math.min(15, change);
              change = Math.max(0, change); // I think it will never happen but check for sure
              // So this is the key point, here we are reducing % of caching blocks
              cache.cacheDataBlockPercent -= change;
              // If we go down too deep we have to stop here, 1% any way should be.
              cache.cacheDataBlockPercent = Math.max(1, cache.cacheDataBlockPercent);
            }
          } else {
            // Well, we have got overshooting.
            // Mayby it is just short-term fluctuation and we can stay in this mode.
            // It help avoid permature exit during short-term fluctuation.
            // If overshooting less than 90%, we will try to increase the percent of
            // caching blocks and hope it is enough.
            if (freedSumMb >= cache.heavyEvictionMbSizeLimit * 0.1) {
              // Simple logic: more overshooting - more caching blocks (backpressure)
              int change = (int) (-freedDataOverheadPercent * 0.1 + 1);
              cache.cacheDataBlockPercent += change;
              // But it can't be more then 100%, so check it.
              cache.cacheDataBlockPercent = Math.min(100, cache.cacheDataBlockPercent);
            } else {
              // Looks like heavy reading is over.
              // Just exit form this mode.
              heavyEvictionCount = 0;
              cache.cacheDataBlockPercent = 100;
            }
          }
          LOG.info("BlockCache evicted (MB): {}, overhead (%): {}, " +
            "heavy eviction counter: {}, " +
            "current caching DataBlock (%): {}",
            freedSumMb, freedDataOverheadPercent,
            heavyEvictionCount, cache.cacheDataBlockPercent);

          freedSumMb = 0;
          startTime = stopTime;
       }

آئیے اب اس سب کو ایک حقیقی مثال کا استعمال کرتے ہوئے دیکھتے ہیں۔ ہمارے پاس درج ذیل ٹیسٹ اسکرپٹ ہے:

  1. آئیے اسکین کرنا شروع کریں (25 تھریڈز، بیچ = 100)
  2. 5 منٹ کے بعد ملٹی گیٹس (25 تھریڈز، بیچ = 100) شامل کریں
  3. 5 منٹ کے بعد، ملٹی گیٹس کو بند کردیں (صرف دوبارہ اسکین باقی ہے)

ہم دو رنز کرتے ہیں، پہلے hbase.lru.cache.heavy.eviction.count.limit = 10000 (جو دراصل فیچر کو غیر فعال کرتا ہے)، اور پھر حد = 0 سیٹ کریں (اسے قابل بناتا ہے)۔

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

لاگ ریجن سرور
بے دخل (ایم بی): 0، تناسب 0.0، اوور ہیڈ (%): -100، بھاری بے دخلی کاؤنٹر: 0، موجودہ کیشنگ ڈیٹا بلاک (٪): 100
بے دخل (ایم بی): 0، تناسب 0.0، اوور ہیڈ (%): -100، بھاری بے دخلی کاؤنٹر: 0، موجودہ کیشنگ ڈیٹا بلاک (٪): 100
بے دخل (ایم بی): 2170، تناسب 1.09، اوور ہیڈ (%): 985، بھاری بے دخلی کاؤنٹر: 1، موجودہ کیشنگ ڈیٹا بلاک (%): 91 < آغاز
بے دخل (ایم بی): 3763، تناسب 1.08، اوور ہیڈ (%): 1781، بھاری بے دخلی کاؤنٹر: 2، موجودہ کیشنگ ڈیٹا بلاک (%): 76
بے دخل (ایم بی): 3306، تناسب 1.07، اوور ہیڈ (%): 1553، بھاری بے دخلی کاؤنٹر: 3، موجودہ کیشنگ ڈیٹا بلاک (%): 61
بے دخل (ایم بی): 2508، تناسب 1.06، اوور ہیڈ (%): 1154، بھاری بے دخلی کاؤنٹر: 4، موجودہ کیشنگ ڈیٹا بلاک (%): 50
بے دخل (ایم بی): 1824، تناسب 1.04، اوور ہیڈ (%): 812، بھاری بے دخلی کاؤنٹر: 5، موجودہ کیشنگ ڈیٹا بلاک (%): 42
بے دخل (ایم بی): 1482، تناسب 1.03، اوور ہیڈ (%): 641، بھاری بے دخلی کاؤنٹر: 6، موجودہ کیشنگ ڈیٹا بلاک (%): 36
بے دخل (ایم بی): 1140، تناسب 1.01، اوور ہیڈ (%): 470، بھاری بے دخلی کاؤنٹر: 7، موجودہ کیشنگ ڈیٹا بلاک (%): 32
بے دخل (ایم بی): 913، تناسب 1.0، اوور ہیڈ (%): 356، بھاری بے دخلی کاؤنٹر: 8، موجودہ کیشنگ ڈیٹا بلاک (%): 29
بے دخل (ایم بی): 912، تناسب 0.89، اوور ہیڈ (%): 356، بھاری بے دخلی کاؤنٹر: 9، موجودہ کیشنگ ڈیٹا بلاک (%): 26
بے دخل (ایم بی): 684، تناسب 0.76، اوور ہیڈ (%): 242، بھاری بے دخلی کاؤنٹر: 10، موجودہ کیشنگ ڈیٹا بلاک (%): 24
بے دخل (ایم بی): 684، تناسب 0.61، اوور ہیڈ (%): 242، بھاری بے دخلی کاؤنٹر: 11، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 456، تناسب 0.51، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 12، موجودہ کیشنگ ڈیٹا بلاک (%): 21
بے دخل (ایم بی): 456، تناسب 0.42، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 13، موجودہ کیشنگ ڈیٹا بلاک (%): 20
بے دخل (ایم بی): 456، تناسب 0.33، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 14، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 15، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 342، تناسب 0.32، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 16، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 342، تناسب 0.31، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 17، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.3، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 18، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.29، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 19، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.27، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 20، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.25، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 21، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.24، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 22، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.22، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 23، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.21، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 24، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.2، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 25، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 228، تناسب 0.17، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 26، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بیدخل (MB): 456، تناسب 0.17، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 27، موجودہ کیشنگ ڈیٹا بلاک (%): 18 < ایڈڈ گیٹس (لیکن ٹیبل وہی ہے)
بے دخل (ایم بی): 456، تناسب 0.15، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 28، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 342، تناسب 0.13، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 29، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 342، تناسب 0.11، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 30، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 342، تناسب 0.09، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 31، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.08، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 32، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.07، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 33، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.06، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 34، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.05، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 35، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.05، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 36، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 228، تناسب 0.04، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 37، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 109، تناسب 0.04، اوور ہیڈ (%): -46، بھاری بے دخلی کاؤنٹر: 37، موجودہ کیشنگ ڈیٹا بلاک (٪): 22 < پیچھے کا دباؤ
بے دخل (ایم بی): 798، تناسب 0.24، اوور ہیڈ (%): 299، بھاری بے دخلی کاؤنٹر: 38، موجودہ کیشنگ ڈیٹا بلاک (%): 20
بے دخل (ایم بی): 798، تناسب 0.29، اوور ہیڈ (%): 299، بھاری بے دخلی کاؤنٹر: 39، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 570، تناسب 0.27، اوور ہیڈ (%): 185، بھاری بے دخلی کاؤنٹر: 40، موجودہ کیشنگ ڈیٹا بلاک (%): 17
بے دخل (ایم بی): 456، تناسب 0.22، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 41، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 342، تناسب 0.16، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 42، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 342، تناسب 0.11، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 43، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 228، تناسب 0.09، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 44، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 228، تناسب 0.07، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 45، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 228، تناسب 0.05، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 46، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بے دخل (ایم بی): 222، تناسب 0.04، اوور ہیڈ (%): 11، بھاری بے دخلی کاؤنٹر: 47، موجودہ کیشنگ ڈیٹا بلاک (%): 16
بیدخل (ایم بی): 104، تناسب 0.03، اوور ہیڈ (%): -48، بھاری بے دخلی کاؤنٹر: 47، موجودہ کیشنگ ڈیٹا بلاک (٪): 21 < رکاوٹ حاصل کرتا ہے
بے دخل (ایم بی): 684، تناسب 0.2، اوور ہیڈ (%): 242، بھاری بے دخلی کاؤنٹر: 48، موجودہ کیشنگ ڈیٹا بلاک (%): 19
بے دخل (ایم بی): 570، تناسب 0.23، اوور ہیڈ (%): 185، بھاری بے دخلی کاؤنٹر: 49، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 342، تناسب 0.22، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 50، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 228، تناسب 0.21، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 51، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 228، تناسب 0.2، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 52، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 228، تناسب 0.18، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 53، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 228، تناسب 0.16، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 54، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 228، تناسب 0.14، اوور ہیڈ (%): 14، بھاری بے دخلی کاؤنٹر: 55، موجودہ کیشنگ ڈیٹا بلاک (%): 18
بے دخل (ایم بی): 112، تناسب 0.14، اوور ہیڈ (%): -44، بھاری بے دخلی کاؤنٹر: 55، موجودہ کیشنگ ڈیٹا بلاک (٪): 23 < پیچھے کا دباؤ
بے دخل (ایم بی): 456، تناسب 0.26، اوور ہیڈ (%): 128، بھاری بے دخلی کاؤنٹر: 56، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.31، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 57، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 58، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 59، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 60، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 61، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 62، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 63، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.32، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 64، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 65، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 66، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.32، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 67، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 68، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.32، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 69، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.32، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 70، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 71، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 72، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 73، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 74، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 75، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 342، تناسب 0.33، اوور ہیڈ (%): 71، بھاری بے دخلی کاؤنٹر: 76، موجودہ کیشنگ ڈیٹا بلاک (%): 22
بے دخل (ایم بی): 21، تناسب 0.33، اوور ہیڈ (%): -90، بھاری بے دخلی کاؤنٹر: 76، موجودہ کیشنگ ڈیٹا بلاک (٪): 32
بے دخل (ایم بی): 0، تناسب 0.0، اوور ہیڈ (%): -100، بھاری بے دخلی کاؤنٹر: 0، موجودہ کیشنگ ڈیٹا بلاک (٪): 100
بے دخل (ایم بی): 0، تناسب 0.0، اوور ہیڈ (%): -100، بھاری بے دخلی کاؤنٹر: 0، موجودہ کیشنگ ڈیٹا بلاک (٪): 100

اسی عمل کو دو کیش سیکشنز کے درمیان تعلق کے گراف کی شکل میں دکھانے کے لیے اسکینز کی ضرورت تھی - سنگل (جہاں بلاکس جن کی پہلے کبھی درخواست نہیں کی گئی تھی) اور ملٹی (ڈیٹا "درخواست کیا گیا" کم از کم ایک بار یہاں محفوظ کیا جاتا ہے):

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

اور آخر میں، ایک گراف کی شکل میں پیرامیٹرز کا آپریشن کیسا نظر آتا ہے۔ موازنے کے لیے، شروع میں کیشے کو مکمل طور پر بند کر دیا گیا تھا، پھر HBase کو کیشنگ کے ساتھ لانچ کیا گیا تھا اور آپٹیمائزیشن کے کام کے آغاز میں 5 منٹ (30 بے دخلی سائیکل) کی تاخیر کی گئی تھی۔

مکمل کوڈ پل کی درخواست میں پایا جا سکتا ہے۔ HBASE 23887 گیتھب پر

تاہم، فی سیکنڈ 300 ہزار ریڈز ان حالات کے تحت اس ہارڈویئر پر حاصل کیا جا سکتا ہے۔ حقیقت یہ ہے کہ جب آپ کو HDFS کے ذریعے ڈیٹا تک رسائی حاصل کرنے کی ضرورت ہوتی ہے، تو ShortCircuitCache (اس کے بعد SSC کہا جاتا ہے) طریقہ کار استعمال کیا جاتا ہے، جو آپ کو نیٹ ورک کے تعاملات سے گریز کرتے ہوئے براہ راست ڈیٹا تک رسائی کی اجازت دیتا ہے۔

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

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

اس کا ادراک کرنے کے بعد، ہم نے محسوس کیا کہ آزاد SSCs کی ایک صف بنا کر مسئلہ کو حل کیا جا سکتا ہے:

private final ShortCircuitCache[] shortCircuitCache;
...
shortCircuitCache = new ShortCircuitCache[this.clientShortCircuitNum];
for (int i = 0; i < this.clientShortCircuitNum; i++)
  this.shortCircuitCache[i] = new ShortCircuitCache(…);

اور پھر ان کے ساتھ کام کریں، چوراہوں کو چھوڑ کر آخری آفسیٹ ہندسے پر بھی:

public ShortCircuitCache getShortCircuitCache(long idx) {
    return shortCircuitCache[(int) (idx % clientShortCircuitNum)];
}

اب آپ جانچ شروع کر سکتے ہیں۔ ایسا کرنے کے لیے، ہم ایک سادہ ملٹی تھریڈ ایپلی کیشن کے ساتھ HDFS سے فائلیں پڑھیں گے۔ پیرامیٹرز مقرر کریں:

conf.set("dfs.client.read.shortcircuit", "true");
conf.set("dfs.client.read.shortcircuit.buffer.size", "65536"); // по дефолту = 1 МБ и это сильно замедляет чтение, поэтому лучше привести в соответствие к реальным нуждам
conf.set("dfs.client.short.circuit.num", num); // от 1 до 10

اور صرف فائلوں کو پڑھیں:

FSDataInputStream in = fileSystem.open(path);
for (int i = 0; i < count; i++) {
    position += 65536;
    if (position > 900000000)
        position = 0L;
    int res = in.read(position, byteBuffer, 0, 65536);
}

اس کوڈ کو الگ الگ تھریڈز میں لاگو کیا جاتا ہے اور ہم بیک وقت پڑھی جانے والی فائلوں کی تعداد (10 سے 200 تک - افقی محور تک) اور کیچز کی تعداد (1 سے 10 تک - گرافکس) میں اضافہ کریں گے۔ عمودی محور اس سرعت کو ظاہر کرتا ہے جو صرف ایک کیش ہونے کی صورت میں SSC میں اضافے کے نتیجے میں ہوتا ہے۔

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

گراف کو کیسے پڑھیں: ایک کیشے کے ساتھ 100 KB بلاکس میں 64 ہزار ریڈز کے لیے عمل درآمد کا وقت 78 سیکنڈ درکار ہے۔ جبکہ 5 کیچز کے ساتھ اس میں 16 سیکنڈ لگتے ہیں۔ وہ. ~ 5 گنا کا ایک ایکسلریشن ہے۔ جیسا کہ گراف سے دیکھا جا سکتا ہے، متوازی ریڈز کی ایک چھوٹی تعداد کے لیے یہ اثر زیادہ نمایاں نہیں ہوتا؛ جب 50 سے زیادہ تھریڈ ریڈز ہوتے ہیں تو یہ نمایاں کردار ادا کرنا شروع کر دیتا ہے۔ یہ بھی قابل توجہ ہے کہ SSCs کی تعداد کو 6 سے بڑھانا اور اوپر ایک نمایاں طور پر چھوٹی کارکردگی میں اضافہ دیتا ہے۔

نوٹ 1: چونکہ ٹیسٹ کے نتائج کافی اتار چڑھاؤ والے ہیں (نیچے دیکھیں)، 3 رنز بنائے گئے اور نتیجے کی قدروں کا اوسط لیا گیا۔

نوٹ 2: بے ترتیب رسائی کو ترتیب دینے سے کارکردگی کا حاصل ایک جیسا ہے، حالانکہ رسائی خود ہی قدرے سست ہے۔

تاہم، یہ واضح کرنا ضروری ہے کہ، HBase کے معاملے کے برعکس، یہ سرعت ہمیشہ مفت نہیں ہوتی۔ یہاں ہم سی پی یو کی مزید کام کرنے کی صلاحیت کو "ان لاک" کرتے ہیں، بجائے اس کے کہ تالے لگ جائیں۔

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

یہاں آپ مشاہدہ کر سکتے ہیں کہ، عام طور پر، کیشز کی تعداد میں اضافہ CPU کے استعمال میں تقریباً متناسب اضافہ دیتا ہے۔ تاہم، کچھ زیادہ جیتنے والے مجموعے ہیں۔

مثال کے طور پر، آئیے SSC = 3 کی ترتیب کو قریب سے دیکھیں۔ رینج پر کارکردگی میں اضافہ تقریباً 3.3 گنا ہے۔ ذیل میں تینوں الگ الگ رنز کے نتائج ہیں۔

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

جبکہ CPU کی کھپت تقریباً 2.8 گنا بڑھ جاتی ہے۔ فرق بہت بڑا نہیں ہے، لیکن چھوٹی گریٹا پہلے ہی خوش ہے اور اس کے پاس اسکول جانے اور سبق لینے کا وقت ہوسکتا ہے۔

اس طرح، یہ کسی بھی ٹول کے لیے مثبت اثر ڈالے گا جو HDFS تک بلک رسائی کا استعمال کرتا ہے (مثال کے طور پر Spark، وغیرہ)، بشرطیکہ ایپلیکیشن کوڈ ہلکا ہو (یعنی پلگ HDFS کلائنٹ کی طرف ہو) اور مفت CPU پاور ہو۔ . چیک کرنے کے لیے، آئیے جانچتے ہیں کہ HBase سے پڑھنے کے لیے BlockCache آپٹیمائزیشن اور SSC ٹیوننگ کے مشترکہ استعمال سے کیا اثر پڑے گا۔

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

یہ دیکھا جا سکتا ہے کہ ایسی حالتوں میں اثر اتنا اچھا نہیں ہوتا جتنا بہتر ٹیسٹوں میں ہوتا ہے (بغیر کسی پروسیسنگ کے پڑھنا)، لیکن یہاں اضافی 80K نچوڑنا کافی ممکن ہے۔ ایک ساتھ، دونوں اصلاحیں 4x اسپیڈ اپ فراہم کرتی ہیں۔

اس اصلاح کے لیے ایک PR بھی بنایا گیا تھا۔ [HDFS-15202]، جسے ضم کر دیا گیا ہے اور یہ فعالیت مستقبل کی ریلیز میں دستیاب ہوگی۔

اور آخر میں، اسی طرح کے وسیع کالم ڈیٹا بیس، کیسینڈرا اور ایچ بیس کی پڑھنے کی کارکردگی کا موازنہ کرنا دلچسپ تھا۔

ایسا کرنے کے لیے، ہم نے دو میزبانوں (مجموعی طور پر 800 تھریڈز) سے معیاری YCSB لوڈ ٹیسٹنگ یوٹیلیٹی کی مثالیں شروع کیں۔ سرور کی طرف - 4 میزبانوں پر RegionServer اور Cassandra کی 4 مثالیں (وہ نہیں جہاں کلائنٹ چل رہے ہیں، ان کے اثر سے بچنے کے لیے)۔ ریڈنگ سائز کے جدولوں سے آئے ہیں:

HBase - HDFS پر 300 GB (100 GB خالص ڈیٹا)

کیسینڈرا - 250 جی بی (نقل کا عنصر = 3)

وہ. حجم تقریبا ایک ہی تھا (HBase میں تھوڑا زیادہ)۔

HBase پیرامیٹرز:

dfs.client.short.circuit.num = 5 (HDFS کلائنٹ کی اصلاح)

hbase.lru.cache.heavy.eviction.count.limit = 30 - اس کا مطلب ہے کہ پیچ 30 بے دخلی (~5 منٹ) کے بعد کام کرنا شروع کر دے گا۔

hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - کیشنگ اور بے دخلی کا ہدف حجم

YCSB لاگز کو ایکسل گرافس میں پارس اور مرتب کیا گیا تھا:

HBase سے پڑھنے کی رفتار کو 3 گنا اور HDFS سے 5 گنا تک کیسے بڑھایا جائے۔

جیسا کہ آپ دیکھ سکتے ہیں، یہ اصلاح ان حالات میں ان ڈیٹا بیس کی کارکردگی کا موازنہ کرنا اور فی سیکنڈ 450 ہزار ریڈز حاصل کرنا ممکن بناتی ہے۔

ہمیں امید ہے کہ یہ معلومات پیداوری کے لیے دلچسپ جدوجہد کے دوران کسی کے لیے کارآمد ثابت ہو سکتی ہے۔

ماخذ: www.habr.com

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