Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Dema ku bi daneyên mezin re dixebitin performansa bilind yek ji wan hewcedariyên sereke ye. Di beşa barkirina daneyê de li Sberbank, em hema hema hemî danûstendinan di nav xweya Data Cloud-a-based Hadoop de derdixin û ji ber vê yekê bi herikînên pir mezin ên agahdariyê re mijûl dibin. Bi xwezayî, em her gav li rêyên çêtirkirina performansê digerin, û naha em dixwazin ji we re vebêjin ka me çawa kariye ku RegionServer HBase û xerîdar HDFS patch bikin, bi saya vê yekê me karî bi girîngî leza xebatên xwendinê zêde bikin.
Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Lêbelê, berî ku hûn biçin ser esasê çêtirkirinan, hêja ye ku meriv li ser sînorkirinên ku, di prensîbê de, ger hûn li ser HDD-ê rûnin, nekarin werin dorpêç kirin.

Çima HDD û xwendina Random Random bi lez hev nagirin
Wekî ku hûn dizanin, HBase, û gelek databasên din, daneyan di blokên bi mezinahiya çend deh kilobyte de hilînin. Bi xwerû ew li ser 64 KB ye. Naha em bifikirin ku pêdivî ye ku em tenê 100 byte bistînin û em ji HBase daxwaz dikin ku bi karanîna mifteyek diyarkirî vê daneyê bide me. Ji ber ku mezinahiya blokê di HFiles de 64 KB ye, daxwaz dê 640 carî (tenê hûrdemek!) ji hewcedariyê mezintir be.

Dûv re, ji ber ku daxwaz dê di nav HDFS û mekanîzmaya cachkirina metadata wê re derbas bibe ShortCircuitCache (ku rê dide gihandina rasterast a pelan), ev dibe sedema xwendina 1 MB ji dîskê. Lêbelê, ev dikare bi parametreyê ve were sererast kirin dfs.client.read.shortcircuit.buffer.size û di gelek rewşan de wateya ku meriv vê nirxê kêm bike, mînakî 126 KB.

Ka em bibêjin ku em wiya dikin, lê ji bilî vê, dema ku em dest bi xwendina daneyan bi navgîniya java api dikin, wek fonksiyonên mîna FileChannel.read û ji pergala xebitandinê dipirsin ku hêjmara daneya diyarkirî bixwîne, ew "tenê di rewşê de" 2 carî bêtir dixwîne. , yanî Di doza me de 256 KB. Ji ber ku java rêyek hêsan nîne ku ala FADV_RANDOM saz bike da ku pêşî li vê tevgerê bigire.

Wekî encamek, ji bo ku em 100 bytes bistînin, 2600 carî bêtir di bin kaxezê de têne xwendin. Wusa dixuye ku çareserî diyar e, bila mezinahiya blokê bi kîlobyte kêm bikin, ala navborî saz bikin û bilezbûnek mezin a ronahiyê bistînin. Lê pirsgirêk ew e ku bi kêmkirina mezinahiya blokê 2 qat, em di heman demê de hejmara baytên ku di her yekîneya demê de têne xwendin 2 carî kêm dikin.

Hin qezenc ji danîna ala FADV_RANDOM-ê dikare were bidestxistin, lê tenê bi pir-têlankirina bilind û bi mezinahiya blokê ya 128 KB, lê ev herî zêde ji sedî çend deh e:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Ceribandin li ser 100 pelan, her yek 1 GB bi mezinahî û li ser 10 HDD-an hatine kirin.

Werin em hesab bikin ka em di prensîbê de, bi vê lezê çi dikarin hesab bikin:
Em bêjin em ji 10 dîskê bi leza 280 MB/sec dixwînin, yanî. 3 milyon car 100 byte. Lê wekî ku tê bîra me, daneyên ku em hewce ne 2600 carî ji ya ku têne xwendin kêmtir e. Bi vî awayî, em 3 mîlyon bi 2600 dabeş dikin û distînin 1100 tomar per second.

Depresyon, ne wisa? Ew xweza ye Random Access gihîştina daneyên li ser HDD - bêyî mezinahiya blokê. Ev sînorê fizîkî ya gihîştina rasthatî ye û tu databas nikare di bin şert û mercên weha de bêtir bişkîne.

Wê hingê databases çawa leza pir zêde bi dest dixin? Ji bo bersiva vê pirsê, em li wêneya jêrîn binêrin ka çi diqewime:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Li vir em dibînin ku ji bo çend hûrdemên pêşîn leza bi rastî li ser hezar tomar di çirkekê de ye. Lêbelê, ji ber vê yekê, ji ber ku ji ya ku tê xwestin pir zêde tê xwendin, dane di qedeh/cache ya pergala xebitandinê (linux) de diqede û leza di çirkeyê de 60 hezar zêde dibe.

Bi vî rengî, bêtir em ê bi lezkirina gihîştina tenê bi daneyên ku di cache OS-ê de ne an jî di cîhazên hilanînê SSD/NVMe yên bi leza gihîştina berawirdî de cih digirin re mijûl bibin.

Di doza me de, em ê ceribandinan li ser rûnek ji 4 serveran pêk bînin, ku her yek bi vî rengî tê barkirin:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 têlan.
Bîr: 730 GB.
guhertoya java: 1.8.0_111

Û li vir xala sereke hêjeya daneyên di tabloyan de ye ku divê were xwendin. Rastî ev e ku heke hûn daneya ji tabloyek ku bi tevahî di cache HBase de hatî danîn bixwînin, wê hingê ew ê negihîje xwendina ji buff / cache ya pergala xebitandinê jî. Ji ber ku HBase ji hêla xwerû ve 40% bîranînê ji avahiyek bi navê BlockCache re vediqetîne. Di bingeh de ev yek ConcurrentHashMap e, ku mifteya wê navê pelê + guheztina blokê ye, û nirx di vê veqetandinê de daneya rastîn e.

Ji ber vê yekê, dema ku tenê ji vê avahiyê dixwînin, em em leza hêja dibînin, mîna mîlyonek daxwazî ​​her çirke. Lê em bifikirin ku em nekarin bi sedan gigabayt bîra tenê ji bo hewcedariyên databasê veqetînin, ji ber ku gelek tiştên din ên kêrhatî li ser van serveran dixebitin hene.

Mînakî, di doza me de, qebareya BlockCache li ser yek RS bi qasî 12 GB ye. Me du RS li ser yek nodek daxist, yanî. 96 GB ji bo BlockCache li ser hemî girêkan têne veqetandin. Û gelek caran bêtir dane hene, mînakî, bila ew bibin 4 tablo, her yek ji 130 herêm, ku tê de pelên mezinahiya wan 800 MB in, ji hêla FAST_DIFF ve têne berhev kirin, yanî. bi tevahî 410 GB (ev daneya paqij e, ango bêyî ku faktora dubarekirinê were hesibandin).

Ji ber vê yekê, BlockCache tenê bi qasî 23% ji tevheviya daneyê ye û ev yek ji şert û mercên rastîn ên ku jê re BigData tê gotin pir nêzîk e. Û li vir e ku kêf dest pê dike - ji ber ku eşkere ye, çend hindiktirîn lêdanên cache, performansa xirabtir. Jixwe, heke hûn bêriya xwe bikin, hûn ê neçar bibin ku gelek karan bikin - ango. dakeve bangkirina fonksiyonên pergalê. Lêbelê, ev nikare were dûr kirin, ji ber vê yekê em werin li aliyek bi tevahî cûda binihêrin - bi daneyên hundurê kaşê re çi dibe?

Ka em rewşê hêsan bikin û bihesibînin ku me cacheyek heye ku tenê bi 1 objektî ve tê. Li vir mînakek e ku dê çi bibe gava ku em hewl bidin ku bi hêjmarek daneyê 3 carî ji cache mezintir bixebitin, divê em:

1. Bloka 1 di cache de cîh bikin
2. Bloka 1-ê ji kaşê derxînin
3. Bloka 2 di cache de cîh bikin
4. Bloka 2-ê ji kaşê derxînin
5. Bloka 3 di cache de cîh bikin

5 çalakî qediyan! Lêbelê, ev rewş nikare normal were gotin; bi rastî, em HBase neçar dikin ku komek karên bi tevahî bêkêr bike. Ew bi domdarî daneyên ji cacheya OS-ê dixwîne, wê li BlockCache-ê bi cih dike, tenê hema tavilê wê bavêje ji ber ku beşek nû ya daneyê hatî. Anîmasyona di destpêka postê de cewhera pirsgirêkê nîşan dide - Berhevkarê Çopê ji pîvanê derdikeve, atmosfer germ dibe, Greta piçûk li Swêdê dûr û germ xemgîn dibe. Û em mirovên IT-ê bi rastî jê hez nakin dema ku zarok xemgîn in, ji ber vê yekê em dest pê dikin ku em li ser çi bikin.

Ger hûn ne hemî blokan têxin kaşê, lê tenê ji sedî diyarkirî ji wan, da ku cache zêde nebe? Ka em dest bi lê zêdekirina tenê çend rêzikên kodê li destpêka fonksiyonê bikin ji bo danîna daneyan li BlockCache:

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

Xala li vir ev e: offset pozîsyona blokê ya di pelê de ye û reqemên wê yên paşîn ji 00 heta 99-an bi awayekî rasthatî û wekhev têne belavkirin. Ji ber vê yekê, em ê tenê yên ku dikevin nav rêza ku ji me re lazim e derbas bikin.

Mînakî, cacheDataBlockPercent = 20 saz bikin û bibînin ka çi diqewime:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Encam diyar e. Di grafikên jêrîn de, zelal dibe ku çima lezek wusa çêbû - em gelek çavkaniyên GC-yê xilas dikin bêyî ku karê Sisyphean-ê danîna daneyan di kaşê de tenê bikin da ku tavilê wê bavêjin xwarê kûçikên Marsî:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Di heman demê de, karanîna CPU zêde dibe, lê ji hilberînê pir kêmtir e:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Di heman demê de hêjayî gotinê ye ku blokên ku di BlockCache de hatine hilanîn cûda ne. Piranî, bi qasî 95%, dane bixwe ye. Û yên mayî metadata ne, wek Parzûnên Bloom an LEAF_INDEX û etc.. Ev dane ne bes e, lê ew pir bikêr e, ji ber ku berî ku rasterast bigihîje daneyan, HBase berê xwe dide meta da ku fêm bike gelo hewce ye ku li vir bêtir lê bigere û, heke wusa be, tam bloka berjewendiyê li ku ye.

Ji ber vê yekê, di kodê de em şertek kontrolê dibînin buf.getBlockType().isData() û bi saya vê metayê, em ê di her rewşê de wê di kaşê de bihêlin.

Naha werin em barkirinê zêde bikin û taybetmendiyê bi yek gavê hûr bikin. Di ceribandina yekem de me rêjeya qutkirinê = 20 çêkir û BlockCache hinekî kêm hate bikar anîn. Naha em wê bikin 23% û her 100 hûrdeman 5 têlan lê zêde bikin da ku bibînin ka têrbûn di kîjan xalê de çêdibe:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Li vir em dibînin ku guhertoya orîjînal hema hema di cih de bi qasî 100 hezar daxwazî ​​di çirkeyê de li ser tavan disekine. Digel ku paç leza 300 hezarî dide. Di heman demê de, diyar e ku lezkirina bêtir êdî ne ew qas "belaş" e; Bikaranîna CPU jî zêde dibe.

Lêbelê, ev ne çareseriyek pir xweşik e, ji ber ku em ji pêş de nizanin ka ji sedî çend blokan pêdivî ye ku were vegirtin, ew bi profîla barkirinê ve girêdayî ye. Ji ber vê yekê, mekanîzmayek hate bicîh kirin ku bixweber vê parametreyê li gorî çalakiya xebatên xwendinê verast bike.

Ji bo kontrolkirina vê sê vebijark hatine zêdekirin:

hbase.lru.cache.heavy.eviction.count.limit - destnîşan dike ku berî ku em dest bi karanîna xweşbîniyê bikin (ango avêtina blokan) divê pêvajoya derxistina daneyan ji cache çend caran bimeşîne. Ji hêla xwerû ve ew bi MAX_INT = 2147483647 wekhev e û bi rastî tê vê wateyê ku taybetmendî dê çu carî dest bi vê nirxê neke. Ji ber ku pêvajoya derxistinê her 5 - 10 çirkeyan dest pê dike (ew bi barkirinê ve girêdayî ye) û 2147483647 * 10 / 60 / 60 / 24 / 365 = 680 sal. Lêbelê, em dikarin vê parameterê li 0-ê destnîşan bikin û taybetmendiyê yekser piştî destpêkirinê bixebitin.

Lêbelê, di vê pîvanê de bargiraniyek jî heye. Ger barê me wisa be ku xwendinên kurt (dibêjin di nav rojê de) û xwendinên demdirêj (bi şev) bi domdarî di nav hev de ne, wê hingê em dikarin pê ewle bibin ku taybetmendî tenê dema ku operasyonên xwendina dirêj di pêşde diçin vebe.

Mînakî, em dizanin ku xwendina kurt-kurt bi gelemperî bi qasî 1 hûrdem dom dike. Ne hewce ye ku meriv dest bi avêtina blokan bike, dê cache nemîne ku demdirêj bibe û dûv re em dikarin vê parametreyê wekî mînak 10 destnîşan bikin. Ev ê bibe sedem ku optimîzasyon tenê gava dirêj- term xwendina çalak dest pê kiriye, ango. di 100 seconds. Bi vî rengî, heke me xwendina kurt-kurt hebe, wê hingê hemî blokan dê bikevin kaşê û dê peyda bibin (ji bilî yên ku dê ji hêla algorîtmaya standard ve werin derxistin). Û gava ku em xwendina dirêj-dirêj dikin, taybetmendî vedibe û dê performansa me pir bilindtir be.

hbase.lru.cache.heavy.eviction.mb.size.limit - destnîşan dike ku em dixwazin di nav 10 çirkeyan de çend megabyte di cache de bi cîh bikin (û, bê guman, derxînin). Taybetmendî dê hewl bide ku bigihîje vê nirxê û wê biparêze. Mesele ev e: heke em gigabaytan bixin nav cache, wê hingê em ê neçar bimînin ku gigabaytan derxînin, û ev, wekî me li jor jî dît, pir biha ye. Lêbelê, divê hûn neceribînin ku wê pir piçûk saz bikin, ji ber ku ev ê bibe sedem ku moda derbasbûna blokê zû derkeve. Ji bo serverên hêzdar (nêzîkî 20-40 core fîzîkî), çêtirîn e ku meriv bi qasî 300-400 MB were danîn. Ji bo çîna navîn (~ 10 core) 200-300 MB. Ji bo pergalên qels (2-5 core) 50-100 MB dibe ku normal be (li ser van nayê ceribandin).

Ka em binihêrin ka ev çawa dixebite: em bibêjin ku me hbase.lru.cache.heavy.eviction.mb.size.limit = 500 danîne, cûreyek barkirin (xwendin) heye û dûv re her ~ 10 çirkeyan em hesab dikin ka çend byte bi karanîna formula:

Serî = Berhev Bîtên Serbestkirî (MB) * 100 / Sînor (MB) - 100;

Ger bi rastî 2000 MB hatibin derxistin, wê hingê Overhead wekhev e:

2000 * 100 / 500 - 100 = 300%

Algorîtmayan hewl didin ku ji çend deh ji sedî zêdetir nemînin, ji ber vê yekê taybetmendî dê ji sedî blokên cached kêm bike, bi vî rengî mekanîzmayek xweser-tunekirinê bicîh tîne.

Lêbelê, heke barkirin dakeve, em bibêjin ku tenê 200 MB têne derxistin û Overhead neyînî dibe (bi navê zêdebûnê):

200 * 100 / 500 - 100 = -60%

Berevajî vê, taybetmendî dê rêjeya blokên cache zêde bike heya ku Overhead erênî bibe.

Li jêr mînakek e ku ev çawa li ser daneyên rastîn xuya dike. Ne hewce ye ku meriv hewl bide ku bigihîje 0%, ne gengaz e. Ew pir baş e dema ku ew bi qasî 30 - 100%, ev dibe alîkar ku meriv di dema lêçûnên demkurt de dev ji derketina zû ji moda xweşbîniyê berde.

hbase.lru.cache.heavy.eviction.overhead.coefficient - destnîşan dike ku em çiqas zû dixwazin encamê bigirin. Ger em teqez zanibin ku xwendinên me bi piranî dirêj in û naxwazin li bendê bin, em dikarin vê rêjeyê zêde bikin û performansa bilind zûtir bistînin.

Mînakî, me ev hevber = 0.01 danî. Ev tê wê wateyê ku Overhead (li jor binêre) dê bi vê hejmarê bi encama encamê re were zêdekirin û rêjeya blokên cache dê kêm bibe. Ka em bihesibînin ku Overhead = 300% û hevber = 0.01, wê hingê rêjeya blokên cache dê 3% kêm bibe.

Mantiqek "Backpressure" ya heman rengî ji bo nirxên Negatîf Overhead (zêdebûn) jî tête bicîh kirin. Ji ber ku guheztinên kurt-kurt ên di hêjmara xwendin û derxistinan de her gav gengaz in, ev mekanîzma dihêle hûn ji derketina pêşwext ji moda xweşbîniyê dûr bikevin. Backpressure xwedan mantiqek berevajî ye: her ku zexmtir be, ew qas bêtir blok têne cach kirin.

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Koda pêkanînê

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

Ka em niha bi mînakek rastîn li van hemîyan binêrin. Me skrîpta testê ya jêrîn heye:

  1. Werin em dest bi kirina Scan bikin (25 mijar, kom = 100)
  2. Piştî 5 hûrdeman, pir-giran zêde bikin (25 mijar, hevî = 100)
  3. Piştî 5 hûrdeman, pir-giran vekin (tenê şopandin dîsa dimîne)

Em du geran dikin, pêşî hbase.lru.cache.heavy.eviction.count.limit = 10000 (ku bi rastî taybetmendiyê asteng dike), û dûv re sînor = 0 destnîşan dike (wê çalak dike).

Di têketinên jêrîn de em dibînin ka taybetmendî çawa tê veguheztin û Overshooting li 14-71%. Dem bi dem bar kêm dibe, ku Backpressure vedike û HBase dîsa blokan vedigire.

Log RegionServer
derxistin (MB)
derxistin (MB)
derxistin (MB): 2170, rêje 1.09, serrî (%): 985, jimareya derxistina giran: 1, cachkirina niha DataBlock (%): 91 < destpêk
derxistin (MB): 3763, rêje 1.08, serrî (%): 1781, jimareya derxistina giran: 2, veşartina niha DataBlock (%): 76
derxistin (MB): 3306, rêje 1.07, serrî (%): 1553, jimareya derxistina giran: 3, veşartina niha DataBlock (%): 61
derxistin (MB): 2508, rêje 1.06, serrî (%): 1154, jimareya derxistina giran: 4, veşartina niha DataBlock (%): 50
derxistin (MB): 1824, rêje 1.04, serrî (%): 812, jimareya derxistina giran: 5, veşartina niha DataBlock (%): 42
derxistin (MB): 1482, rêje 1.03, serrî (%): 641, jimareya derxistina giran: 6, veşartina niha DataBlock (%): 36
derxistin (MB): 1140, rêje 1.01, serrî (%): 470, jimareya derxistina giran: 7, veşartina niha DataBlock (%): 32
derxistin (MB): 913, rêje 1.0, serrî (%): 356, jimareya derxistina giran: 8, veşartina niha DataBlock (%): 29
derxistin (MB): 912, rêje 0.89, serrî (%): 356, jimareya derxistina giran: 9, veşartina niha DataBlock (%): 26
derxistin (MB): 684, rêje 0.76, serrî (%): 242, jimareya derxistina giran: 10, veşartina niha DataBlock (%): 24
derxistin (MB): 684, rêje 0.61, serrî (%): 242, jimareya derxistina giran: 11, veşartina niha DataBlock (%): 22
derxistin (MB): 456, rêje 0.51, serrî (%): 128, jimareya derxistina giran: 12, veşartina niha DataBlock (%): 21
derxistin (MB): 456, rêje 0.42, serrî (%): 128, jimareya derxistina giran: 13, veşartina niha DataBlock (%): 20
derxistin (MB): 456, rêje 0.33, serrî (%): 128, jimareya derxistina giran: 14, veşartina niha DataBlock (%): 19
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 15, veşartina niha DataBlock (%): 19
derxistin (MB): 342, rêje 0.32, serrî (%): 71, jimareya derxistina giran: 16, veşartina niha DataBlock (%): 19
derxistin (MB): 342, rêje 0.31, serrî (%): 71, jimareya derxistina giran: 17, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.3, serrî (%): 14, jimareya derxistina giran: 18, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.29, serrî (%): 14, jimareya derxistina giran: 19, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.27, serrî (%): 14, jimareya derxistina giran: 20, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.25, serrî (%): 14, jimareya derxistina giran: 21, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.24, serrî (%): 14, jimareya derxistina giran: 22, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.22, serrî (%): 14, jimareya derxistina giran: 23, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.21, serrî (%): 14, jimareya derxistina giran: 24, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.2, serrî (%): 14, jimareya derxistina giran: 25, veşartina niha DataBlock (%): 19
derxistin (MB): 228, rêje 0.17, serrî (%): 14, jimareya derxistina giran: 26, veşartina niha DataBlock (%): 19
derxistin (MB): 456, rêje 0.17, serrî (%): 128, jimareya derxistina giran: 27, vekêşana heyî DataBlock (%): 18 < zêde dibe (lê tablo heman e)
derxistin (MB): 456, rêje 0.15, serrî (%): 128, jimareya derxistina giran: 28, veşartina niha DataBlock (%): 17
derxistin (MB): 342, rêje 0.13, serrî (%): 71, jimareya derxistina giran: 29, veşartina niha DataBlock (%): 17
derxistin (MB): 342, rêje 0.11, serrî (%): 71, jimareya derxistina giran: 30, veşartina niha DataBlock (%): 17
derxistin (MB): 342, rêje 0.09, serrî (%): 71, jimareya derxistina giran: 31, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.08, serrî (%): 14, jimareya derxistina giran: 32, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.07, serrî (%): 14, jimareya derxistina giran: 33, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.06, serrî (%): 14, jimareya derxistina giran: 34, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.05, serrî (%): 14, jimareya derxistina giran: 35, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.05, serrî (%): 14, jimareya derxistina giran: 36, veşartina niha DataBlock (%): 17
derxistin (MB): 228, rêje 0.04, serrî (%): 14, jimareya derxistina giran: 37, veşartina niha DataBlock (%): 17
derxistin (MB): 109, rêje 0.04, serrî (%): -46, jimareya derxistina giran: 37, cachkirina niha DataBlock (%): 22 < tansiyona paş
derxistin (MB): 798, rêje 0.24, serrî (%): 299, jimareya derxistina giran: 38, veşartina niha DataBlock (%): 20
derxistin (MB): 798, rêje 0.29, serrî (%): 299, jimareya derxistina giran: 39, veşartina niha DataBlock (%): 18
derxistin (MB): 570, rêje 0.27, serrî (%): 185, jimareya derxistina giran: 40, veşartina niha DataBlock (%): 17
derxistin (MB): 456, rêje 0.22, serrî (%): 128, jimareya derxistina giran: 41, veşartina niha DataBlock (%): 16
derxistin (MB): 342, rêje 0.16, serrî (%): 71, jimareya derxistina giran: 42, veşartina niha DataBlock (%): 16
derxistin (MB): 342, rêje 0.11, serrî (%): 71, jimareya derxistina giran: 43, veşartina niha DataBlock (%): 16
derxistin (MB): 228, rêje 0.09, serrî (%): 14, jimareya derxistina giran: 44, veşartina niha DataBlock (%): 16
derxistin (MB): 228, rêje 0.07, serrî (%): 14, jimareya derxistina giran: 45, veşartina niha DataBlock (%): 16
derxistin (MB): 228, rêje 0.05, serrî (%): 14, jimareya derxistina giran: 46, veşartina niha DataBlock (%): 16
derxistin (MB): 222, rêje 0.04, serrî (%): 11, jimareya derxistina giran: 47, veşartina niha DataBlock (%): 16
derxistin (MB): 104, rêje 0.03, serrî (%): -48, jimareya derxistina giran: 47, cachkirina heyî DataBlock (%): 21 < navbirî dibe
derxistin (MB): 684, rêje 0.2, serrî (%): 242, jimareya derxistina giran: 48, veşartina niha DataBlock (%): 19
derxistin (MB): 570, rêje 0.23, serrî (%): 185, jimareya derxistina giran: 49, veşartina niha DataBlock (%): 18
derxistin (MB): 342, rêje 0.22, serrî (%): 71, jimareya derxistina giran: 50, veşartina niha DataBlock (%): 18
derxistin (MB): 228, rêje 0.21, serrî (%): 14, jimareya derxistina giran: 51, veşartina niha DataBlock (%): 18
derxistin (MB): 228, rêje 0.2, serrî (%): 14, jimareya derxistina giran: 52, veşartina niha DataBlock (%): 18
derxistin (MB): 228, rêje 0.18, serrî (%): 14, jimareya derxistina giran: 53, veşartina niha DataBlock (%): 18
derxistin (MB): 228, rêje 0.16, serrî (%): 14, jimareya derxistina giran: 54, veşartina niha DataBlock (%): 18
derxistin (MB): 228, rêje 0.14, serrî (%): 14, jimareya derxistina giran: 55, veşartina niha DataBlock (%): 18
derxistin (MB): 112, rêje 0.14, serrî (%): -44, jimareya derxistina giran: 55, cachkirina niha DataBlock (%): 23 < tansiyona paş
derxistin (MB): 456, rêje 0.26, serrî (%): 128, jimareya derxistina giran: 56, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.31, serrî (%): 71, jimareya derxistina giran: 57, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 58, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 59, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 60, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 61, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 62, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 63, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.32, serrî (%): 71, jimareya derxistina giran: 64, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 65, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 66, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.32, serrî (%): 71, jimareya derxistina giran: 67, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 68, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.32, serrî (%): 71, jimareya derxistina giran: 69, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.32, serrî (%): 71, jimareya derxistina giran: 70, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 71, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 72, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 73, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 74, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 75, veşartina niha DataBlock (%): 22
derxistin (MB): 342, rêje 0.33, serrî (%): 71, jimareya derxistina giran: 76, veşartina niha DataBlock (%): 22
derxistin (MB)
derxistin (MB)
derxistin (MB)

Skenandin hewce bûn ku heman pêvajoyê di forma grafîkî ya têkiliya di navbera du beşên cache de nîşan bidin - yekane (ku blokên ku berê qet nehatine xwestin) û pirjimar (daneyên "daxwaz" bi kêmanî carekê li vir têne hilanîn):

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Û di dawiyê de, operasyona parametreyan di forma grafîkê de çawa xuya dike. Ji bo berhevdanê, cache di destpêkê de bi tevahî hate qut kirin, dûv re HBase bi cachkirinê hate destpêkirin û destpêka xebata xweşbîniyê 5 hûrdem (30 çerxên derxistinê) dereng xist.

Tevahiya kodê dikare di Daxwaza Pêl de were dîtin HBASE 23887 li ser github.

Lêbelê, 300 hezar xwendin di çirkeyê de ne hemî tiştê ku li ser vê hardware di van şertan de têne bidestxistin e. Rastî ev e ku gava ku hûn hewce ne ku hûn bi riya HDFS-ê bigihîjin daneyan, mekanîzmaya ShortCircuitCache (li vir wekî SSC tê binav kirin) tê bikar anîn, ku dihêle hûn rasterast bigihîjin daneyan, ji danûstendinên torê dûr bikevin.

Profîlkirinê destnîşan kir ku her çend ev mekanîzmayek destkeftiyek mezin dide jî, ew di heman demê de dibe xelekek, ji ber ku hema hema hemî operasyonên giran di hundurê qeflekê de çêdibin, ku pir caran dibe sedema astengkirinê.

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Piştî ku em vê yekê fêm kirin, me fêm kir ku pirsgirêk dikare bi afirandina komek SSC-yên serbixwe were dorpêç kirin:

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

Û dûv re bi wan re bixebitin, di heman demê de di jimareya paşîn a paşîn de jî xaçerêyan ji holê rakin:

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

Niha hûn dikarin dest bi ceribandinê bikin. Ji bo vê yekê, em ê pelên ji HDFS-ê bi serîlêdanek pir-mijalek hêsan bixwînin. Parametreyan saz bikin:

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

Û tenê pelan bixwînin:

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

Ev kod di nav mijarên cihêreng de tê darve kirin û em ê hejmara pelên hevdem têne xwendin (ji 10 ber 200 - eksê horizontî) û hejmara cache (ji 1 heya 10 - grafîk) zêde bikin. Axîna vertîkal leza ku ji zêdebûna SSC-ê ve girêdayî ye li gorî rewşa ku tenê yek cache heye nîşan dide.

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Meriv çawa grafikê dixwîne: Dema bicihkirinê ji bo 100 hezar xwendina di blokên 64 KB de bi yek cache 78 saniyeyan hewce dike. Digel ku bi 5 cacheyan 16 saniye digire. Ewan. lezbûnek ~ 5 caran heye. Wekî ku ji grafîkê tê dîtin, bandor ji bo hejmarek piçûk xwendinên paralel pir ne diyar e; dema ku ji 50 xwendinê zêdetir be, ew dest bi rolek berbiçav dike. Her weha tê xuyang kirin ku jimara SSC ji 6 zêde dibe. û li jor zêdebûnek performansa pir piçûktir dide.

Nîşe 1: ji ber ku encamên testê pir guhezbar in (li jêr binêre), 3 rêve kirin û nirxên encam têne navîn.

Nîşe 2: Qezenckirina performansê ya ji mîhengkirina gihîştina rasthatî yek e, her çend gihîştin bixwe hinekî hêdîtir e.

Lêbelê, pêdivî ye ku were zelal kirin ku, berevajî doza HBase, ev lezbûn her gav ne belaş e. Li vir em şiyana CPU-yê ku bêtir kar dike, li şûna ku li ser qefleyan daliqîne, "vekin".

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Li vir hûn dikarin bibînin ku, bi gelemperî, zêdebûna hejmara cache-ê di karanîna CPU-ê de bi qasî hevseng zêdebûnek dide. Lêbelê, hevberdanên piçûktir ên serketî hene.

Mînakî, em ji nêz ve li mîhengê SSC = 3 binêrin. Zêdebûna performansê li ser rêzê bi qasî 3.3 carî ye. Li jêr encamên ji her sê beşên cuda hene.

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Dema ku mezaxtina CPU bi qasî 2.8 carî zêde dibe. Cûdahî ne pir mezin e, lê Gretaya piçûk jixwe kêfxweş e û dibe ku dem hebe ku here dibistanê û dersan bigire.

Ji ber vê yekê, ev ê ji bo her amûrek ku gihandina girseyî ya HDFS-ê bikar tîne (mînakî Spark, hwd.) bandorek erênî hebe, bi şertê ku koda serîlêdanê sivik be (ango fîşa li milê xerîdar HDFS ye) û hêza CPU-ya belaş hebe. . Ji bo kontrolkirinê, em biceribînin ka dê karanîna hevgirtî ya xweşbînkirina BlockCache û ahenga SSC ji bo xwendina ji HBase çi bandorek hebe.

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Tê dîtin ku di bin şert û mercên weha de bandor ne ew qas mezin e ku di ceribandinên safîkirî de (xwendin bêyî pêvajoyek), lê pir mimkun e ku meriv 80K zêde li vir derxe. Bi hev re, her du optimîzasyon bi lezbûna 4x peyda dikin.

Ji bo vê xweşbîniyê jî PR hate çêkirin [HDFS-15202], ku hatiye yek kirin û ev fonksiyon dê di weşanên pêşerojê de peyda bibe.

Û di dawiyê de, balkêş bû ku meriv performansa xwendinê ya databasek stûnek fireh, Cassandra û HBase bide ber hev.

Ji bo kirina vê, me ji du mêvandaran (bi tevahî 800 mijarên) kargêriya ceribandina barkirinê ya standard YCSB dest pê kir. Li aliyê serverê - 4 mînakên RegionServer û Cassandra li ser 4 mêvandar (ne yên ku xerîdar lê dimeşînin, da ku ji bandora wan dûr bikevin). Xwendin ji tabloyên mezinbûnê hatin:

HBase - 300 GB li ser HDFS (100 GB daneya paqij)

Cassandra - 250 GB (faktora dubarekirinê = 3)

Ewan. deng hema hema yek bû (li HBase hinekî din).

Parametreyên HBase:

dfs.client.short.circuit.num = 5 (Optimîzasyona xerîdar HDFS)

hbase.lru.cache.heavy.eviction.count.limit = 30 - ev tê vê wateyê ku patch dê piştî 30 derxistinan (~ 5 hûrdem) dest bi xebatê bike

hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - Hêjmara armanc a cachkirin û derxistinê

Têketinên YCSB hatin parsandin û di grafikên Excel de hatin berhev kirin:

Meriv çawa leza xwendinê ji HBase 3 carî û ji HDFS heya 5 carî zêde dike

Wekî ku hûn dikarin bibînin, van xweşbîniyan gengaz dike ku meriv performansa van databasan di van şert û mercan de bide ber hev û di çirkeyê de 450 hezar xwendinê bi dest bixe.

Em hêvî dikin ku ev agahdarî di dema tekoşîna balkêş a ji bo hilberînê de ji kesek re kêrhatî be.

Source: www.habr.com

Add a comment