Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Utendaji wa juu ni moja ya mahitaji muhimu wakati wa kufanya kazi na data kubwa. Katika idara ya upakiaji data huko Sberbank, tunasukuma karibu miamala yote kwenye Wingu letu la Data la Hadoop na kwa hivyo tunashughulikia mtiririko mkubwa wa habari. Kwa kawaida, sisi daima tunatafuta njia za kuboresha utendaji, na sasa tunataka kukuambia jinsi tulivyoweza kuweka kiraka RegionServer HBase na mteja wa HDFS, shukrani ambayo tuliweza kuongeza kwa kiasi kikubwa kasi ya shughuli za kusoma.
Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Walakini, kabla ya kuendelea na kiini cha maboresho, inafaa kuzungumza juu ya vizuizi ambavyo, kwa kanuni, haziwezi kuepukwa ikiwa unakaa kwenye HDD.

Kwa nini HDD na usomaji wa haraka wa Ufikiaji Nasibu hauoani
Kama unavyojua, HBase, na hifadhidata nyingine nyingi, huhifadhi data katika vizuizi vya makumi kadhaa ya kilobaiti kwa ukubwa. Kwa chaguo-msingi ni kuhusu 64 KB. Sasa hebu tufikirie kuwa tunahitaji kupata baiti 100 pekee na tunaomba HBase itupe data hii kwa kutumia ufunguo fulani. Kwa kuwa ukubwa wa block katika HFiles ni 64 KB, ombi litakuwa kubwa mara 640 (dakika moja tu!) kuliko inavyohitajika.

Ifuatayo, kwa kuwa ombi litapitia HDFS na utaratibu wake wa kuhifadhi metadata ShortCircuitCache (ambayo inaruhusu upatikanaji wa moja kwa moja kwa faili), hii inasababisha kusoma tayari 1 MB kutoka kwenye diski. Hata hivyo, hii inaweza kubadilishwa na parameter dfs.client.read.shortcircuit.buffer.size na katika hali nyingi ni mantiki kupunguza thamani hii, kwa mfano hadi 126 KB.

Wacha tuseme tufanye hivi, lakini kwa kuongeza, tunapoanza kusoma data kupitia java api, kama vile kazi kama FileChannel.read na uulize mfumo wa uendeshaji usome idadi maalum ya data, inasoma "ikiwa tu" mara 2 zaidi. , i.e. 256 KB kwa upande wetu. Hii ni kwa sababu java haina njia rahisi ya kuweka alama ya FADV_RANDOM ili kuzuia tabia hii.

Matokeo yake, kupata byte zetu 100, mara 2600 zaidi husomwa chini ya kofia. Inaweza kuonekana kuwa suluhisho ni dhahiri, wacha tupunguze saizi ya block hadi kilobyte, weka bendera iliyotajwa na upate kasi kubwa ya kutaalamika. Lakini shida ni kwamba kwa kupunguza saizi ya block kwa mara 2, tunapunguza pia idadi ya baiti zilizosomwa kwa kila kitengo cha wakati kwa mara 2.

Manufaa fulani kutokana na kuweka bendera ya FADV_RANDOM yanaweza kupatikana, lakini tu kwa nyuzi nyingi za juu na kwa ukubwa wa block ya 128 KB, lakini hii ni kiwango cha juu cha makumi kadhaa ya asilimia:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Majaribio yalifanywa kwenye faili 100, kila moja ikiwa na ukubwa wa GB 1 na ziko kwenye HDD 10.

Wacha tuhesabu kile tunaweza, kwa kanuni, kutegemea kwa kasi hii:
Hebu sema tunasoma kutoka kwa disks 10 kwa kasi ya 280 MB / sec, i.e. Milioni 3 mara 100 ka. Lakini tunapokumbuka, data tunayohitaji ni mara 2600 chini ya ile inayosomwa. Kwa hivyo, tunagawanya milioni 3 kwa 2600 na kupata Rekodi 1100 kwa sekunde.

Inasikitisha, sivyo? Hiyo ni asili Upataji Random upatikanaji wa data kwenye HDD - bila kujali ukubwa wa kuzuia. Hiki ndicho kikomo halisi cha ufikiaji bila mpangilio na hakuna hifadhidata inayoweza kubana zaidi chini ya hali kama hizo.

Je! hifadhidata hufikiaje kasi ya juu zaidi? Ili kujibu swali hili, hebu tuangalie kile kinachotokea kwenye picha ifuatayo:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Hapa tunaona kwamba kwa dakika chache za kwanza kasi ni kweli kuhusu rekodi elfu kwa sekunde. Walakini, zaidi, kwa sababu ya ukweli kwamba mengi zaidi yanasomwa kuliko ilivyoombwa, data huishia kwenye buff/cache ya mfumo wa uendeshaji (linux) na kasi huongezeka hadi elfu 60 bora kwa sekunde.

Kwa hivyo, zaidi tutashughulika na kuongeza kasi ya ufikiaji tu kwa data iliyo kwenye kashe ya Mfumo wa Uendeshaji au iliyo katika vifaa vya uhifadhi vya SSD/NVMe vya kasi ya ufikiaji inayolinganishwa.

Kwa upande wetu, tutafanya vipimo kwenye benchi ya seva 4, ambayo kila moja inashtakiwa kama ifuatavyo.

CPU: Xeon E5-2680 v4 @ nyuzi 2.40GHz 64.
Kumbukumbu: 730 GB.
toleo la java: 1.8.0_111

Na hapa jambo muhimu ni kiasi cha data katika meza ambazo zinahitajika kusoma. Ukweli ni kwamba ikiwa unasoma data kutoka kwa meza ambayo imewekwa kabisa kwenye cache ya HBase, basi haitakuja hata kusoma kutoka kwa buff / cache ya mfumo wa uendeshaji. Kwa sababu HBase kwa chaguo-msingi hutenga 40% ya kumbukumbu kwa muundo unaoitwa BlockCache. Kimsingi hii ni ConcurrentHashMap, ambapo ufunguo ni jina la faili + kukabiliana na kizuizi, na thamani ni data halisi katika kukabiliana na hii.

Kwa hivyo, tunaposoma tu kutoka kwa muundo huu, sisi tunaona kasi nzuri, kama maombi milioni kwa sekunde. Lakini hebu tufikirie kuwa hatuwezi kutenga mamia ya gigabaiti za kumbukumbu kwa mahitaji ya hifadhidata tu, kwa sababu kuna vitu vingine vingi muhimu vinavyoendeshwa kwenye seva hizi.

Kwa mfano, kwa upande wetu, kiasi cha BlockCache kwenye RS moja ni kuhusu 12 GB. Tulipanda RS mbili kwenye node moja, i.e. GB 96 zimetengwa kwa BlockCache kwenye nodi zote. Na kuna data mara nyingi zaidi, kwa mfano, basi iwe ni meza 4, mikoa 130 kila moja, ambayo faili ni 800 MB kwa ukubwa, imesisitizwa na FAST_DIFF, i.e. jumla ya GB 410 (hii ni data safi, i.e. bila kuzingatia sababu ya kurudia).

Kwa hivyo, BlockCache ni karibu 23% tu ya jumla ya kiasi cha data na hii ni karibu zaidi na hali halisi ya kile kinachoitwa BigData. Na hapa ndipo furaha huanza - kwa sababu ni wazi, kache chache hupiga, utendaji mbaya zaidi. Baada ya yote, ikiwa unakosa, utakuwa na kazi nyingi - i.e. nenda chini kwa utendakazi wa mfumo wa kupiga. Hata hivyo, hii haiwezi kuepukwa, basi hebu tuangalie kipengele tofauti kabisa - nini kinatokea kwa data ndani ya cache?

Wacha turahisishe hali hiyo na tufikirie kuwa tuna kache ambayo inafaa tu kitu 1. Hapa kuna mfano wa kile kitakachotokea tunapojaribu kufanya kazi na kiasi cha data mara 3 zaidi kuliko kache, tutalazimika:

1. Weka kizuizi 1 kwenye kashe
2. Ondoa kizuizi 1 kutoka kwa kache
3. Weka kizuizi 2 kwenye kashe
4. Ondoa kizuizi 2 kutoka kwa kache
5. Weka kizuizi 3 kwenye kashe

Vitendo 5 vimekamilika! Walakini, hali hii haiwezi kuitwa kawaida; kwa kweli, tunalazimisha HBase kufanya rundo la kazi isiyo na maana kabisa. Inasoma data kutoka kwa kashe ya OS kila wakati, inaiweka kwenye BlockCache, na kuitupa mara moja kwa sababu sehemu mpya ya data imefika. Uhuishaji ulio mwanzoni mwa chapisho unaonyesha kiini cha tatizo - Kikusanya takataka kinaenda kwa kasi, hali ya anga inaongezeka, Greta mdogo aliye Uswidi ya mbali na yenye joto jingi anakasirika. Na sisi watu wa IT kwa kweli hatupendi wakati watoto wana huzuni, kwa hivyo tunaanza kufikiria juu ya kile tunaweza kufanya juu yake.

Je, ikiwa huweka vizuizi vyote kwenye cache, lakini asilimia fulani tu yao, ili cache haina kufurika? Wacha tuanze kwa kuongeza tu mistari michache ya nambari hadi mwanzo wa kazi ya kuweka data kwenye BlockCache:

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

Hatua hapa ni ifuatayo: kukabiliana ni nafasi ya kuzuia katika faili na tarakimu zake za mwisho zinasambazwa kwa nasibu na sawasawa kutoka 00 hadi 99. Kwa hiyo, tutaruka tu wale wanaoanguka kwenye safu tunayohitaji.

Kwa mfano, weka cacheDataBlockPercent = 20 na uone kitakachotokea:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Matokeo yake ni dhahiri. Katika grafu hapa chini, inakuwa wazi kwa nini kasi kama hiyo ilitokea - tunaokoa rasilimali nyingi za GC bila kufanya kazi ya Sisyphean ya kuweka data kwenye kashe tu ili kuitupa mara moja chini ya bomba la mbwa wa Martian:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Wakati huo huo, matumizi ya CPU huongezeka, lakini ni kidogo sana kuliko tija:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Pia ni muhimu kuzingatia kwamba vitalu vilivyohifadhiwa katika BlockCache ni tofauti. Wengi, karibu 95%, ni data yenyewe. Na iliyosalia ni metadata, kama vile vichungi vya Bloom au LEAF_INDEX na Ρ‚.Π΄.. Data hii haitoshi, lakini ni muhimu sana, kwa sababu kabla ya kupata data moja kwa moja, HBase inageuka kwenye meta ili kuelewa ikiwa ni muhimu kutafuta hapa zaidi na, ikiwa ni hivyo, wapi hasa block ya riba iko.

Kwa hiyo, katika kanuni tunaona hali ya kuangalia buf.getBlockType().isData() na shukrani kwa meta hii, tutaiacha kwenye kache kwa hali yoyote.

Sasa hebu tuongeze mzigo na kaza kipengele kidogo kwa kwenda moja. Katika jaribio la kwanza tulifanya asilimia ya kukata = 20 na BlockCache haikutumiwa kidogo. Sasa wacha tuiweke kwa 23% na tuongeze nyuzi 100 kila dakika 5 ili kuona ni wakati gani kueneza kunatokea:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Hapa tunaona kwamba toleo la asili karibu mara moja linapiga dari kwa maombi elfu 100 kwa sekunde. Wakati kiraka kinaongeza kasi ya hadi 300 elfu. Wakati huo huo, ni wazi kuwa kuongeza kasi zaidi sio "bure" tena; utumiaji wa CPU pia unaongezeka.

Hata hivyo, hii sio suluhisho la kifahari sana, kwani hatujui mapema ni asilimia ngapi ya vitalu vinavyohitaji kuhifadhiwa, inategemea wasifu wa mzigo. Kwa hiyo, utaratibu ulitekelezwa ili kurekebisha moja kwa moja parameter hii kulingana na shughuli za shughuli za kusoma.

Chaguzi tatu zimeongezwa ili kudhibiti hili:

hbase.lru.cache.heavy.eviction.count.kikomo - huweka ni mara ngapi mchakato wa kutoa data kutoka kwa akiba unapaswa kutekelezwa kabla ya kuanza kutumia uboreshaji (yaani kuruka vizuizi). Kwa chaguo-msingi ni sawa na MAX_INT = 2147483647 na kwa kweli ina maana kwamba kipengele hakitaanza kufanya kazi na thamani hii. Kwa sababu mchakato wa kufukuzwa huanza kila sekunde 5 - 10 (inategemea mzigo) na 2147483647 * 10/60/60/24/365 = 680 miaka. Hata hivyo, tunaweza kuweka kigezo hiki hadi 0 na kufanya kipengele kifanye kazi mara baada ya uzinduzi.

Hata hivyo, pia kuna mzigo wa malipo katika parameter hii. Ikiwa mzigo wetu ni kwamba usomaji wa muda mfupi (sema wakati wa mchana) na usomaji wa muda mrefu (usiku) unaingiliana kila wakati, basi tunaweza kuhakikisha kuwa kipengele kimewashwa tu wakati shughuli za kusoma kwa muda mrefu zinaendelea.

Kwa mfano, tunajua kwamba usomaji wa muda mfupi kwa kawaida huchukua kama dakika 1. Hakuna haja ya kuanza kutupa vizuizi, kashe haitakuwa na wakati wa kupitwa na wakati na kisha tunaweza kuweka parameter hii sawa na, kwa mfano, 10. Hii itasababisha ukweli kwamba uboreshaji utaanza kufanya kazi tu wakati wa muda mrefu- usomaji wa neno amilifu umeanza, i.e. katika sekunde 100. Kwa hivyo, ikiwa tuna usomaji wa muda mfupi, basi vitalu vyote vitaingia kwenye cache na vitapatikana (isipokuwa kwa wale ambao watafukuzwa na algorithm ya kawaida). Na tunaposoma kwa muda mrefu, kipengele huwashwa na tutakuwa na utendakazi wa juu zaidi.

hbase.lru.cache.heavy.eviction.mb.size.limit - huweka ni megabaiti ngapi tungependa kuweka kwenye akiba (na, bila shaka, kuondoa) katika sekunde 10. Kipengele hiki kitajaribu kufikia thamani hii na kuidumisha. Jambo ni hili: ikiwa tunasukuma gigabytes kwenye cache, basi tutalazimika kumfukuza gigabytes, na hii, kama tulivyoona hapo juu, ni ghali sana. Walakini, haupaswi kujaribu kuiweka ndogo sana, kwani hii itasababisha hali ya kuruka kuzuia kutoka mapema. Kwa seva zenye nguvu (kuhusu 20-40 cores kimwili), ni mojawapo ya kuweka kuhusu 300-400 MB. Kwa darasa la kati (~ 10 cores) 200-300 MB. Kwa mifumo dhaifu (2-5 cores) 50-100 MB inaweza kuwa ya kawaida (haijajaribiwa kwenye haya).

Wacha tuangalie jinsi hii inavyofanya kazi: wacha tuseme tuliweka hbase.lru.cache.heavy.eviction.mb.size.limit = 500, kuna aina fulani ya mzigo (kusoma) na kisha kila ~ sekunde 10 tunahesabu ni ka ngapi. kufukuzwa kwa kutumia formula:

Juu = Jumla ya Baiti Zilizotolewa (MB) * 100 / Kikomo (MB) - 100;

Ikiwa kwa kweli 2000 MB zilifukuzwa, basi Overhead ni sawa na:

2000 * 100 / 500 - 100 = 300%

Algoriti hujaribu kudumisha si zaidi ya makumi kadhaa ya asilimia, kwa hivyo kipengele kitapunguza asilimia ya vizuizi vilivyohifadhiwa, na hivyo kutekeleza utaratibu wa kurekebisha kiotomatiki.

Walakini, ikiwa mzigo unashuka, wacha tuseme MB 200 tu ndizo zimefukuzwa na Rudia inakuwa mbaya (kinachojulikana kama kupindukia):

200 * 100 / 500 - 100 = -60%

Kinyume chake, kipengele kitaongeza asilimia ya vizuizi vilivyoakibishwa hadi Upeo wa Juu uwe mzuri.

Chini ni mfano wa jinsi hii inavyoonekana kwenye data halisi. Hakuna haja ya kujaribu kufikia 0%, haiwezekani. Ni nzuri sana ikiwa ni karibu 30 - 100%, hii husaidia kuzuia kutoka mapema kutoka kwa hali ya uboreshaji wakati wa upasuaji wa muda mfupi.

hbase.lru.cache.heavy.eviction.overhead.mgawo - huweka jinsi tungependa kupata matokeo haraka. Ikiwa tunajua kwa hakika kwamba usomaji wetu mara nyingi ni mrefu na hatutaki kusubiri, tunaweza kuongeza uwiano huu na kupata utendakazi wa juu kwa haraka zaidi.

Kwa mfano, tunaweka mgawo huu = 0.01. Hii inamaanisha kuwa Sehemu ya Juu (tazama hapo juu) itazidishwa na nambari hii kwa matokeo na asilimia ya vizuizi vilivyohifadhiwa itapunguzwa. Hebu tuchukue kwamba Overhead = 300% na mgawo = 0.01, basi asilimia ya vitalu vya cached itapungua kwa 3%.

Mantiki sawa ya "Backpressure" pia inatekelezwa kwa maadili hasi ya Juu (kupiga risasi kupita kiasi). Kwa kuwa kushuka kwa thamani kwa muda mfupi kwa kiasi cha usomaji na kufukuzwa kunawezekana kila wakati, utaratibu huu hukuruhusu kuzuia kutoka mapema kutoka kwa modi ya uboreshaji. Shinikizo la nyuma lina mantiki iliyogeuzwa: kadiri upigaji risasi ulivyo na nguvu zaidi, ndivyo vizuizi vingi vimehifadhiwa.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Kanuni ya utekelezaji

        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;
       }

Hebu sasa tuangalie haya yote kwa kutumia mfano halisi. Tunayo hati ifuatayo ya jaribio:

  1. Wacha tuanze kufanya Scan (nyuzi 25, bechi = 100)
  2. Baada ya dakika 5, ongeza vitu vingi (nyuzi 25, bechi = 100)
  3. Baada ya dakika 5, zima upataji mwingi (uchanganuzi pekee unabaki tena)

Tunafanya mikimbio mbili, kwanza hbase.lru.cache.heavy.eviction.count.limit = 10000 (ambayo huzima kipengele), na kisha kuweka kikomo = 0 (kuiwezesha).

Katika kumbukumbu hapa chini tunaona jinsi kipengele kimewashwa na kuweka upya Overshooting hadi 14-71%. Mara kwa mara mzigo hupungua, ambayo huwasha Backpressure na HBase huhifadhi vizuizi zaidi tena.

Ingia MkoaServer
iliyofukuzwa (MB): 0, uwiano 0.0, sehemu ya juu (%): -100, kaunta nzito ya uondoaji: 0, Kizuizi cha sasa cha akiba (%): 100
iliyofukuzwa (MB): 0, uwiano 0.0, sehemu ya juu (%): -100, kaunta nzito ya uondoaji: 0, Kizuizi cha sasa cha akiba (%): 100
iliyoondolewa (MB): 2170, uwiano 1.09, sehemu ya juu (%): 985, kaunta nzito ya uondoaji: 1, Uhifadhi wa sasa wa DataBlock (%): 91 < start
iliyofukuzwa (MB): 3763, uwiano 1.08, juu (%): 1781, kaunta nzito ya kufukuza: 2, DataBlock ya sasa ya akiba (%): 76
iliyofukuzwa (MB): 3306, uwiano 1.07, juu (%): 1553, kaunta nzito ya kufukuza: 3, DataBlock ya sasa ya akiba (%): 61
iliyofukuzwa (MB): 2508, uwiano 1.06, juu (%): 1154, kaunta nzito ya kufukuza: 4, DataBlock ya sasa ya akiba (%): 50
iliyofukuzwa (MB): 1824, uwiano 1.04, juu (%): 812, kaunta nzito ya kufukuza: 5, DataBlock ya sasa ya akiba (%): 42
iliyofukuzwa (MB): 1482, uwiano 1.03, juu (%): 641, kaunta nzito ya kufukuza: 6, DataBlock ya sasa ya akiba (%): 36
iliyofukuzwa (MB): 1140, uwiano 1.01, juu (%): 470, kaunta nzito ya kufukuza: 7, DataBlock ya sasa ya akiba (%): 32
iliyofukuzwa (MB): 913, uwiano 1.0, juu (%): 356, kaunta nzito ya kufukuza: 8, DataBlock ya sasa ya akiba (%): 29
iliyofukuzwa (MB): 912, uwiano 0.89, juu (%): 356, kaunta nzito ya kufukuza: 9, DataBlock ya sasa ya akiba (%): 26
iliyofukuzwa (MB): 684, uwiano 0.76, juu (%): 242, kaunta nzito ya kufukuza: 10, DataBlock ya sasa ya akiba (%): 24
iliyofukuzwa (MB): 684, uwiano 0.61, juu (%): 242, kaunta nzito ya kufukuza: 11, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 456, uwiano 0.51, juu (%): 128, kaunta nzito ya kufukuza: 12, DataBlock ya sasa ya akiba (%): 21
iliyofukuzwa (MB): 456, uwiano 0.42, juu (%): 128, kaunta nzito ya kufukuza: 13, DataBlock ya sasa ya akiba (%): 20
iliyofukuzwa (MB): 456, uwiano 0.33, juu (%): 128, kaunta nzito ya kufukuza: 14, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 15, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 342, uwiano 0.32, juu (%): 71, kaunta nzito ya kufukuza: 16, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 342, uwiano 0.31, juu (%): 71, kaunta nzito ya kufukuza: 17, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.3, juu (%): 14, kaunta nzito ya kufukuza: 18, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.29, juu (%): 14, kaunta nzito ya kufukuza: 19, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.27, juu (%): 14, kaunta nzito ya kufukuza: 20, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.25, juu (%): 14, kaunta nzito ya kufukuza: 21, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.24, juu (%): 14, kaunta nzito ya kufukuza: 22, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.22, juu (%): 14, kaunta nzito ya kufukuza: 23, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.21, juu (%): 14, kaunta nzito ya kufukuza: 24, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.2, juu (%): 14, kaunta nzito ya kufukuza: 25, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 228, uwiano 0.17, juu (%): 14, kaunta nzito ya kufukuza: 26, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 456, uwiano 0.17, sehemu ya juu (%): 128, kaunta nzito ya kufukuza: 27, Uhifadhi wa sasa wa DataBlock (%): 18 < imeongezwa inapata (lakini jedwali sawa)
iliyofukuzwa (MB): 456, uwiano 0.15, juu (%): 128, kaunta nzito ya kufukuza: 28, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 342, uwiano 0.13, juu (%): 71, kaunta nzito ya kufukuza: 29, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 342, uwiano 0.11, juu (%): 71, kaunta nzito ya kufukuza: 30, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 342, uwiano 0.09, juu (%): 71, kaunta nzito ya kufukuza: 31, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.08, juu (%): 14, kaunta nzito ya kufukuza: 32, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.07, juu (%): 14, kaunta nzito ya kufukuza: 33, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.06, juu (%): 14, kaunta nzito ya kufukuza: 34, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.05, juu (%): 14, kaunta nzito ya kufukuza: 35, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.05, juu (%): 14, kaunta nzito ya kufukuza: 36, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 228, uwiano 0.04, juu (%): 14, kaunta nzito ya kufukuza: 37, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 109, uwiano 0.04, sehemu ya juu (%): -46, kaunta nzito ya uondoaji: 37, Uhifadhi wa sasa wa DataBlock (%): 22 < shinikizo la nyuma
iliyofukuzwa (MB): 798, uwiano 0.24, juu (%): 299, kaunta nzito ya kufukuza: 38, DataBlock ya sasa ya akiba (%): 20
iliyofukuzwa (MB): 798, uwiano 0.29, juu (%): 299, kaunta nzito ya kufukuza: 39, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 570, uwiano 0.27, juu (%): 185, kaunta nzito ya kufukuza: 40, DataBlock ya sasa ya akiba (%): 17
iliyofukuzwa (MB): 456, uwiano 0.22, juu (%): 128, kaunta nzito ya kufukuza: 41, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 342, uwiano 0.16, juu (%): 71, kaunta nzito ya kufukuza: 42, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 342, uwiano 0.11, juu (%): 71, kaunta nzito ya kufukuza: 43, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 228, uwiano 0.09, juu (%): 14, kaunta nzito ya kufukuza: 44, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 228, uwiano 0.07, juu (%): 14, kaunta nzito ya kufukuza: 45, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 228, uwiano 0.05, juu (%): 14, kaunta nzito ya kufukuza: 46, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 222, uwiano 0.04, juu (%): 11, kaunta nzito ya kufukuza: 47, DataBlock ya sasa ya akiba (%): 16
iliyofukuzwa (MB): 104, uwiano 0.03, sehemu ya juu (%): -48, kaunta nzito ya uondoaji: 47, Uhifadhi wa sasa wa DataBlock (%): 21 < kukatiza kunapata
iliyofukuzwa (MB): 684, uwiano 0.2, juu (%): 242, kaunta nzito ya kufukuza: 48, DataBlock ya sasa ya akiba (%): 19
iliyofukuzwa (MB): 570, uwiano 0.23, juu (%): 185, kaunta nzito ya kufukuza: 49, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 342, uwiano 0.22, juu (%): 71, kaunta nzito ya kufukuza: 50, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 228, uwiano 0.21, juu (%): 14, kaunta nzito ya kufukuza: 51, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 228, uwiano 0.2, juu (%): 14, kaunta nzito ya kufukuza: 52, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 228, uwiano 0.18, juu (%): 14, kaunta nzito ya kufukuza: 53, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 228, uwiano 0.16, juu (%): 14, kaunta nzito ya kufukuza: 54, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 228, uwiano 0.14, juu (%): 14, kaunta nzito ya kufukuza: 55, DataBlock ya sasa ya akiba (%): 18
iliyofukuzwa (MB): 112, uwiano 0.14, sehemu ya juu (%): -44, kaunta nzito ya uondoaji: 55, Uhifadhi wa sasa wa DataBlock (%): 23 < shinikizo la nyuma
iliyofukuzwa (MB): 456, uwiano 0.26, juu (%): 128, kaunta nzito ya kufukuza: 56, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.31, juu (%): 71, kaunta nzito ya kufukuza: 57, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 58, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 59, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 60, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 61, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 62, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 63, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.32, juu (%): 71, kaunta nzito ya kufukuza: 64, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 65, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 66, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.32, juu (%): 71, kaunta nzito ya kufukuza: 67, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 68, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.32, juu (%): 71, kaunta nzito ya kufukuza: 69, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.32, juu (%): 71, kaunta nzito ya kufukuza: 70, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 71, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 72, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 73, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 74, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 75, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 342, uwiano 0.33, juu (%): 71, kaunta nzito ya kufukuza: 76, DataBlock ya sasa ya akiba (%): 22
iliyofukuzwa (MB): 21, uwiano 0.33, sehemu ya juu (%): -90, kaunta nzito ya uondoaji: 76, Kizuizi cha sasa cha akiba (%): 32
iliyofukuzwa (MB): 0, uwiano 0.0, sehemu ya juu (%): -100, kaunta nzito ya uondoaji: 0, Kizuizi cha sasa cha akiba (%): 100
iliyofukuzwa (MB): 0, uwiano 0.0, sehemu ya juu (%): -100, kaunta nzito ya uondoaji: 0, Kizuizi cha sasa cha akiba (%): 100

Uchanganuzi ulihitajika ili kuonyesha mchakato sawa katika mfumo wa grafu ya uhusiano kati ya sehemu mbili za kache - moja (ambapo vizuizi ambavyo havijawahi kuombwa hapo awali) na anuwai (data "iliyoombwa" angalau mara moja huhifadhiwa hapa):

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Na hatimaye, uendeshaji wa vigezo unaonekanaje katika mfumo wa grafu. Kwa kulinganisha, kache ilizimwa kabisa mwanzoni, kisha HBase ilizinduliwa na caching na kuchelewesha kuanza kwa kazi ya uboreshaji kwa dakika 5 (mizunguko 30 ya kufukuzwa).

Nambari kamili inaweza kupatikana katika Ombi la Kuvuta HBASE 23887 kwenye github.

Walakini, kusoma elfu 300 kwa sekunde sio yote ambayo yanaweza kupatikana kwenye vifaa hivi chini ya hali hizi. Ukweli ni kwamba wakati unahitaji kupata data kupitia HDFS, utaratibu wa ShortCircuitCache (hapa unajulikana kama SSC) hutumiwa, ambayo inakuwezesha kufikia data moja kwa moja, kuepuka mwingiliano wa mtandao.

Uchambuzi ulionyesha kuwa ingawa utaratibu huu unatoa faida kubwa, pia wakati fulani unakuwa kizuizi, kwa sababu karibu shughuli zote nzito hufanyika ndani ya kufuli, ambayo husababisha kuzuia wakati mwingi.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Baada ya kugundua hili, tuligundua kuwa shida inaweza kuepukwa kwa kuunda safu ya SSC huru:

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

Na kisha fanya kazi nao, ukiondoa makutano pia kwenye nambari ya mwisho ya kumaliza:

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

Sasa unaweza kuanza kupima. Ili kufanya hivyo, tutasoma faili kutoka kwa HDFS na programu rahisi ya nyuzi nyingi. Weka vigezo:

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

Na soma faili tu:

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);
}

Nambari hii inatekelezwa kwa nyuzi tofauti na tutaongeza idadi ya faili zilizosomwa wakati huo huo (kutoka 10 hadi 200 - mhimili wa usawa) na idadi ya caches (kutoka 1 hadi 10 - graphics). Mhimili wima unaonyesha kasi inayotokana na ongezeko la SSC kuhusiana na kesi wakati kuna kache moja tu.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Jinsi ya kusoma grafu: Wakati wa utekelezaji wa elfu 100 unasomwa katika vizuizi vya KB 64 na kashe moja inahitaji sekunde 78. Ambapo kwa kache 5 inachukua sekunde 16. Wale. kuna kuongeza kasi ya ~ mara 5. Kama inavyoonekana kutoka kwa grafu, athari haionekani sana kwa idadi ndogo ya usomaji sambamba; huanza kuchukua jukumu dhahiri wakati kuna usomaji zaidi ya 50. Pia inaonekana kuwa kuongeza idadi ya SSC kutoka 6. na hapo juu inatoa ongezeko dogo la utendaji.

Kumbuka 1: kwa kuwa matokeo ya mtihani ni tete kabisa (tazama hapa chini), kukimbia 3 kulifanyika na maadili yaliyotokana yalikuwa wastani.

Kumbuka 2: Faida ya utendaji kutokana na kusanidi ufikiaji bila mpangilio ni sawa, ingawa ufikiaji wenyewe ni wa polepole kidogo.

Walakini, inahitajika kufafanua kuwa, tofauti na kesi ya HBase, kuongeza kasi hii sio bure kila wakati. Hapa "tunafungua" uwezo wa CPU kufanya kazi zaidi, badala ya kunyongwa kwenye kufuli.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Hapa unaweza kuona kwamba, kwa ujumla, ongezeko la idadi ya kache hutoa ongezeko la takriban sawia katika utumiaji wa CPU. Walakini, kuna mchanganyiko zaidi wa kushinda.

Kwa mfano, hebu tuangalie kwa karibu mpangilio wa SSC = 3. Ongezeko la utendaji kwenye masafa ni karibu mara 3.3. Chini ni matokeo kutoka kwa mbio zote tatu tofauti.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Wakati matumizi ya CPU huongezeka kwa takriban mara 2.8. Tofauti sio kubwa sana, lakini Greta mdogo tayari ana furaha na anaweza kuwa na wakati wa kuhudhuria shule na kuchukua masomo.

Kwa hivyo, hii itakuwa na athari chanya kwa zana yoyote inayotumia ufikiaji wa HDFS kwa wingi (kwa mfano Spark, n.k.), mradi tu nambari ya programu ni nyepesi (yaani, plagi iko upande wa mteja wa HDFS) na kuna nguvu ya bure ya CPU. . Ili kuangalia, hebu tujaribu matumizi ya pamoja ya uboreshaji wa BlockCache na urekebishaji wa SSC kwa usomaji kutoka HBase yatakuwa na athari gani.

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Inaweza kuonekana kuwa chini ya hali kama hizi athari sio kubwa kama katika vipimo vilivyosafishwa (kusoma bila usindikaji wowote), lakini inawezekana kabisa kufinya 80K ya ziada hapa. Kwa pamoja, uboreshaji wote hutoa hadi kasi ya 4x.

PR pia iliundwa kwa uboreshaji huu [HDFS-15202], ambayo imeunganishwa na utendakazi huu utapatikana katika matoleo yajayo.

Na hatimaye, ilikuwa ya kuvutia kulinganisha utendaji wa usomaji wa hifadhidata ya safu wima pana sawa, Cassandra na HBase.

Ili kufanya hivyo, tulizindua matukio ya matumizi ya kawaida ya kupima mzigo wa YCSB kutoka kwa wapangishi wawili (nyuzi 800 kwa jumla). Kwa upande wa seva - matukio 4 ya RegionServer na Cassandra kwenye majeshi 4 (sio wale ambapo wateja wanaendesha, ili kuepuka ushawishi wao). Usomaji ulitoka kwa meza za ukubwa:

HBase - GB 300 kwenye HDFS (data safi ya GB 100)

Cassandra - GB 250 (sababu ya kurudia = 3)

Wale. kiasi kilikuwa takriban sawa (katika HBase zaidi kidogo).

Vigezo vya HBase:

dfs.client.short.circuit.num = 5 (Uboreshaji wa mteja wa HDFS)

hbase.lru.cache.heavy.eviction.count.limit = 30 - hii inamaanisha kuwa kiraka kitaanza kufanya kazi baada ya kufukuzwa 30 (~ dakika 5)

hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - lengwa la kiasi cha akiba na kufukuzwa

Kumbukumbu za YCSB zilichanganuliwa na kukusanywa kuwa grafu za Excel:

Jinsi ya kuongeza kasi ya kusoma kutoka HBase hadi mara 3 na kutoka HDFS hadi mara 5

Kama unaweza kuona, uboreshaji huu hufanya iwezekanavyo kulinganisha utendaji wa hifadhidata hizi chini ya hali hizi na kufikia usomaji 450 kwa sekunde.

Tunatumahi kuwa habari hii inaweza kuwa muhimu kwa mtu wakati wa mapambano ya kusisimua ya uzalishaji.

Chanzo: mapenzi.com

Kuongeza maoni