Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Kinerja anu luhur mangrupikeun salah sahiji syarat konci nalika damel sareng data ageung. Dina departemén loading data di Sberbank, urang ngompa ampir kabéh transaksi kana kami basis Hadoop Data Cloud sahingga nungkulan aliran bener badag inpormasi. Alami, urang salawasna pilari cara pikeun ngaronjatkeun kinerja, sarta ayeuna urang rék ngabejaan ka maneh kumaha urang junun patch RegionServer HBase jeung klien HDFS, hatur nuhun nu kami bisa nyata ngaronjatkeun laju operasi maca.
Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Nanging, sateuacan ngalih kana hakekat perbaikan, éta patut ngobrol ngeunaan larangan anu, prinsipna, teu tiasa dihindari upami anjeun calik dina HDD.

Naha HDD sareng Bacaan Random Access gancang henteu cocog
Sakumaha anjeun terang, HBase, sareng seueur pangkalan data sanésna, nyimpen data dina blok sababaraha puluhan kilobyte ukuranana. Sacara standar éta ngeunaan 64 KB. Ayeuna hayu urang bayangkeun yén urang ngan ukur kedah nampi 100 bait sareng naroskeun ka HBase pikeun masihan kami data ieu nganggo konci anu tangtu. Kusabab ukuran blok dina HFiles nyaeta 64 KB, pamundut bakal 640 kali leuwih badag (ngan hiji menit!) ti diperlukeun.

Salajengna, saprak pamundut bakal ngaliwat HDFS sareng mékanisme cache metadata na ShortCircuitCache (anu ngamungkinkeun aksés langsung ka file), ieu ngakibatkeun maca geus 1 MB ti disk. Nanging, ieu tiasa disaluyukeun sareng parameter dfs.client.read.shortcircuit.buffer.size sarta dina loba kasus ngajadikeun rasa ngurangan nilai ieu, contona 126 KB.

Sebutkeun urang ngalakukeun ieu, tapi salian ti éta, nalika urang ngamimitian maca data ngalangkungan java api, sapertos fungsi sapertos FileChannel.read sareng naroskeun sistem operasi maca jumlah data anu ditangtukeun, éta berbunyi "bisi bisi" 2 kali langkung. , i.e. 256 KB dina hal urang. Ieu kusabab java teu gaduh cara anu gampang pikeun nyetél bandéra FADV_RANDOM pikeun nyegah kabiasaan ieu.

Hasilna, pikeun meunangkeun 100 bait urang, 2600 kali leuwih dibaca handapeun tiung. Éta sigana yén solusina écés, hayu urang ngirangan ukuran blok kana kilobyte, nyetél bendera anu disebatkeun sareng kéngingkeun akselerasi pencerahan anu saé. Tapi masalahna nyaéta ku ngirangan ukuran blok ku 2 kali, urang ogé ngirangan jumlah bait anu dibaca per unit waktos ku 2 kali.

Sababaraha kauntungan tina netepkeun bandéra FADV_RANDOM tiasa didapet, tapi ngan ku multi-threading anu luhur sareng ukuran blok 128 KB, tapi ieu maksimal sababaraha puluh persén:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Tés dilaksanakeun dina 100 file, masing-masing ukuran 1 GB sareng ayana dina 10 HDD.

Hayu urang ngitung naon anu urang tiasa, prinsipna, cacah dina laju ieu:
Anggap urang maca tina 10 disk dina laju 280 MB/detik, i.e. 3 juta kali 100 bait. Tapi sakumaha urang émut, data anu urang peryogikeun nyaéta 2600 kali langkung handap tina anu dibaca. Ku kituna, urang bagikeun 3 juta ku 2600 sarta meunang 1100 rékaman per detik.

Depressing, teu eta? Éta alam Aksés acak aksés ka data dina HDD - paduli ukuran blok. Ieu wates fisik aksés acak sarta euweuh database bisa squeeze kaluar leuwih dina kaayaan kitu.

Kumaha lajeng database ngahontal speeds loba nu leuwih luhur? Pikeun ngajawab patarosan ieu, hayu urang tingali naon anu lumangsung dina gambar di handap ieu:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Di dieu urang nempo yén pikeun sababaraha menit kahiji laju bener ngeunaan sarébu rékaman per detik. Sanajan kitu, salajengna, alatan kanyataan yén leuwih loba dibaca ti ieu dipénta, data ends up dina buff / cache tina sistem operasi (linux) jeung speed naek kana leuwih santun 60 sarébu per detik.

Ku kituna, salajengna urang bakal nungkulan accelerating aksés ukur kana data nu aya dina cache OS atawa lokasina di SSD / alat panyimpen NVMe laju aksés comparable.

Dina hal urang, urang bakal ngalaksanakeun tés dina bangku 4 server, anu masing-masing ditagihkeun sapertos kieu:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 benang.
Mémori: 730 GB.
Vérsi java: 1.8.0_111

Sareng di dieu titik konci nyaéta jumlah data dina tabel anu kedah dibaca. Kanyataan yén lamun maca data tina tabel nu sagemblengna disimpen dina cache HBase, lajeng malah moal datang ka bacaan ti buff sistem operasi urang / cache. Kusabab HBase sacara standar allocates 40% memori ka struktur disebut BlockCache. Intina ieu mangrupikeun ConcurrentHashMap, dimana koncina nyaéta nami file + offset blok, sareng nilaina nyaéta data saleresna dina offset ieu.

Ku kituna, nalika maca ukur tina struktur ieu, urang urang tingali speed alus teuing, kawas sajuta requests per detik. Tapi hayu urang ngabayangkeun yén urang teu bisa allocate ratusan gigabytes memori ngan pikeun kaperluan database, sabab aya loba hal mangpaat séjén ngajalankeun on server ieu.

Salaku conto, dina kasus urang, volume BlockCache dina hiji RS sakitar 12 GB. Urang landed dua RS dina hiji titik, i.e. 96 GB dialokasikeun pikeun BlockCache dina sadaya titik. Sareng aya sababaraha kali langkung seueur data, contona, 4 méja, masing-masing 130 daérah, dimana file ukuranana 800 MB, dikomprés ku FAST_DIFF, i.e. total 410 GB (ieu data murni, i.e. tanpa nyokot kana akun faktor réplikasi).

Ku kituna, BlockCache ngan ukur ngeunaan 23% tina total volume data sareng ieu langkung caket kana kaayaan nyata anu disebut BigData. Sareng ieu dimana kasenangan dimimitian - sabab écés, pangsaeutikna cache hits, langkung parah prestasina. Barina ogé, lamun sono, anjeun bakal kudu ngalakukeun loba karya - i.e. turun ka nelepon fungsi sistem. Sanajan kitu, ieu teu bisa dihindari, jadi hayu urang nempo hiji aspék lengkep beda - naon kajadian ka data dina cache nu?

Hayu urang simplify kaayaan sarta nganggap yen urang boga cache nu ngan fits 1 obyék. Ieu conto naon anu bakal kajadian nalika urang nyobian damel sareng volume data 3 kali langkung ageung tibatan cache, urang kedah:

1. Teundeun blok 1 dina cache
2. Cabut blok 1 tina cache
3. Teundeun blok 2 dina cache
4. Cabut blok 2 tina cache
5. Teundeun blok 3 dina cache

5 lampah réngsé! Nanging, kaayaan ieu henteu tiasa disebat normal; kanyataanna, urang maksa HBase pikeun ngalakukeun sakumpulan padamelan anu teu aya gunana. Éta teras-terasan maca data tina cache OS, nempatkeun éta di BlockCache, ngan ukur ngalungkeun éta ampir langsung kusabab bagian data énggal parantos sumping. Animasi dina awal tulisan nunjukkeun hakekat masalah - Kolektor Sampah nuju kaluar skala, atmosfir panas, sakedik Greta di Swedia anu jauh sareng panas janten kesel. Jeung urang IT urang bener teu resep lamun barudak keur sedih, jadi urang mimitian mikir ngeunaan naon bisa urang pigawé ngeunaan eta.

Kumaha upami anjeun nempatkeun henteu sadayana blok dina cache, tapi ngan ukur perséntase anu tangtu, supados cache henteu ngabahekeun? Hayu urang mimitian ku ngan ukur nambihan sababaraha baris kode ka awal fungsi pikeun nempatkeun data kana BlockCache:

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

Intina di dieu nyaéta kieu: offset nyaéta posisi blok dina file sareng digit terakhirna sacara acak sareng disebarkeun merata tina 00 dugi ka 99. Kituna, urang ngan ukur bakal ngalangkungan anu digolongkeun kana rentang anu urang peryogikeun.

Contona, set cacheDataBlockPercent = 20 tur tingal kumaha kajadian:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Hasilna écés. Dina grafik di handap, janten jelas naha akselerasi misalna hiji lumangsung - urang nyimpen loba sumberdaya GC tanpa ngalakukeun pagawean Sisyphean nempatkeun data dina cache ngan langsung ngalungkeun eta ka solokan tina anjing Martian:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Dina waktos anu sami, pamakean CPU ningkat, tapi langkung handap tina produktivitas:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Éta ogé sia ​​noting yén blok disimpen dina BlockCache béda. Paling, ngeunaan 95%, data sorangan. Sareng sésana nyaéta metadata, sapertos saringan Bloom atanapi LEAF_INDEX sareng jsb.. Data ieu henteu cekap, tapi mangpaat pisan, sabab sateuacan ngaksés data langsung, HBase tos ka meta pikeun ngartos naha perlu milarian di dieu langkung jauh sareng, upami kitu, dimana persisna blok anu dipikaresep.

Ku alatan éta, dina kode urang ningali kaayaan dipariksa buf.getBlockType().isData() jeung berkat meta ieu, urang bakal ninggalkeun eta dina cache dina sagala hal.

Ayeuna hayu urang ningkatkeun beban jeung rada tighten up fitur dina hiji lebet. Dina tés munggaran urang nyieun persentase cutoff = 20 sarta BlockCache ieu rada underutilized. Ayeuna hayu urang setel ka 23% sareng tambahkeun 100 utas unggal 5 menit pikeun ningali dimana titik jenuh lumangsung:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Di dieu urang nempo yén versi aslina ampir langsung pencét siling di ngeunaan 100 sarébu requests per detik. Sedengkeun patch méré akselerasi nepi ka 300 rébu. Dina waktos anu sami, écés yén akselerasi salajengna henteu deui "gratis"; Pamakéan CPU ogé ningkat.

Nanging, ieu sanés mangrupikeun solusi anu elegan, sabab urang henteu terang sateuacanna naon persentase blok anu kedah di-cache, éta gumantung kana profil beban. Ku alatan éta, mékanisme ieu dilaksanakeun pikeun otomatis nyaluyukeun parameter ieu gumantung kana aktivitas operasi maca.

Tilu pilihan geus ditambahkeun pikeun ngadalikeun ieu:

hbase.lru.cache.heavy.eviction.count.limit — Nyetél sabaraha kali prosés ngusir data tina cache kedah dijalankeun sateuacan urang mimitian nganggo optimasi (nyaéta ngaluncurkeun blok). Sacara standar éta sarua jeung MAX_INT = 2147483647 sarta dina kanyataanana ngandung harti yén fitur moal ngamimitian gawé bareng nilai ieu. Kusabab prosés nundung dimimitian unggal 5 - 10 detik (éta gumantung kana beban) jeung 2147483647 * 10 / 60 / 60 / 24 / 365 = 680 taun. Nanging, urang tiasa nyetél parameter ieu ka 0 sareng ngajantenkeun fitur éta langsung saatos peluncuran.

Sanajan kitu, aya ogé payload dina parameter ieu. Upami beban urang sapertos anu maca jangka pondok (sebutkeun siang) sareng bacaan jangka panjang (peuting) terus-terusan diselingi, maka urang tiasa mastikeun yén fiturna dihurungkeun ngan ukur nalika operasi maca panjang nuju lumangsung.

Salaku conto, urang terang yén bacaan jangka pondok biasana salami 1 menit. Aya teu kudu ngamimitian buang kaluar blok, cache moal boga waktu pikeun jadi luntur lajeng urang tiasa nyetél parameter ieu sarua jeung, contona, 10. Ieu bakal ngakibatkeun kanyataan yén optimasi bakal ngamimitian gawéna ngan lamun lila- istilah bacaan aktif geus dimimitian, i.e. dina 100 detik. Janten, upami urang gaduh bacaan jangka pondok, maka sadaya blok bakal lebet kana cache sareng bakal sayogi (iwal jalma anu bakal digusur ku algoritma standar). Sareng nalika urang ngalakukeun bacaan jangka panjang, fiturna dihurungkeun sareng urang bakal ngagaduhan prestasi anu langkung luhur.

hbase.lru.cache.heavy.eviction.mb.size.limit - nangtukeun sabaraha megabytes urang hoyong nempatkeun dina cache (jeung, tangtosna, nundung) dina 10 detik. Fitur bakal nyobian ngahontal nilai ieu sareng ngajaga éta. Intina nyaéta kieu: upami urang nyorong gigabytes kana cache, maka urang kedah ngusir gigabyte, sareng ieu, sapertos anu urang tingali di luhur, mahal pisan. Nanging, anjeun teu kedah nyobian nyetél éta sakedik teuing, sabab ieu bakal nyababkeun modeu blok skip kaluar sateuacanna. Pikeun server kuat (kira-kira 20-40 inti fisik), éta optimal pikeun nyetél ngeunaan 300-400 MB. Pikeun kelas menengah (~ 10 cores) 200-300 MB. Pikeun sistem lemah (2-5 cores) 50-100 MB bisa jadi normal (teu diuji dina ieu).

Hayu urang tingali kumaha ieu jalanna: hayu urang nyetél hbase.lru.cache.heavy.eviction.mb.size.limit = 500, aya sababaraha jinis beban (maca) teras unggal ~ 10 detik urang ngitung sabaraha bait éta. digusur ngagunakeun rumus:

Overhead = Jumlah bait bébas (MB) * 100 / Wates (MB) - 100;

Upami kanyataanna 2000 MB digusur, maka Overhead sami sareng:

2000 * 100 / 500 - 100 = 300%

Algoritma nyobian ngajaga henteu langkung ti sababaraha puluhan persén, ku kituna fitur éta bakal ngirangan persentase blok sindangan, ku kituna ngalaksanakeun mékanisme tuning otomatis.

Nanging, upami bebanna turun, anggap ngan ukur 200 MB anu digusur sareng Overhead janten négatip (anu disebut overshooting):

200 * 100 / 500 - 100 = -60%

Sabalikna, fitur éta bakal ningkatkeun persentase blok sindangan dugi ka Overhead janten positip.

Di handap ieu conto kumaha ieu kasampak dina data nyata. Teu kedah nyobian ngahontal 0%, mustahil. Hal ieu kacida alus lamun éta ngeunaan 30 - 100%, ieu mantuan pikeun nyegah kaluar prématur tina mode optimasi salila surges jangka pondok.

hbase.lru.cache.heavy.eviction.overhead.coefficient - nangtukeun sabaraha gancang urang hayang meunang hasilna. Upami urang terang pasti yén bacaan urang biasana panjang sareng henteu hoyong ngantosan, urang tiasa ningkatkeun rasio ieu sareng kéngingkeun kinerja anu langkung gancang.

Contona, urang nyetel koefisien ieu = 0.01. Ieu ngandung harti yén Overhead (tempo di luhur) bakal dikali jumlah ieu ku hasil hasilna jeung persentase blok sindangan bakal ngurangan. Hayu urang nganggap yén Overhead = 300% jeung koefisien = 0.01, mangka persentase blok sindangan bakal ngurangan ku 3%.

Logika "Backpressure" anu sami ogé dilaksanakeun pikeun nilai Overhead négatip (overshooting). Kusabab fluctuations jangka pondok dina volume bacaan na evictions salawasna mungkin, mékanisme ieu ngidinan Anjeun pikeun nyingkahan kaluar prématur tina mode optimasi. Backpressure boga logika inverted: leuwih kuat overshooting, beuki blok anu sindangan.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Kode palaksanaan

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

Hayu urang ayeuna ningali sadayana ieu nganggo conto nyata. Kami ngagaduhan skrip tés ieu:

  1. Hayu urang mimitian ngalakukeun Scan (25 threads, bets = 100)
  2. Sanggeus 5 menit, tambahkeun multi-meunang (25 threads, bets = 100)
  3. Saatos 5 menit, mareuman multi-get (ngan scan tetep deui)

Urang ngalakukeun dua ngalir, kahiji hbase.lru.cache.heavy.eviction.count.limit = 10000 (nu sabenerna disables fitur nu), lajeng set wates = 0 (ngaktifkeun).

Dina log di handap urang tingali kumaha fitur dihurungkeun tur ngareset Overshooting ka 14-71%. Ti jaman ka jaman nurun beban, nu ngahurungkeun Backpressure na HBase caches leuwih blok deui.

Log RegionServer
digusur (MB): 0, rasio 0.0, overhead (%): -100, counter nundung beurat: 0, ayeuna cache DataBlock (%): 100
digusur (MB): 0, rasio 0.0, overhead (%): -100, counter nundung beurat: 0, ayeuna cache DataBlock (%): 100
digusur (MB): 2170, rasio 1.09, overhead (%): 985, counter nundung beurat: 1, ayeuna cache DataBlock (%): 91 <mimiti
digusur (MB): 3763, rasio 1.08, overhead (%): 1781, counter nundung beurat: 2, ayeuna cache DataBlock (%): 76
digusur (MB): 3306, rasio 1.07, overhead (%): 1553, counter nundung beurat: 3, ayeuna cache DataBlock (%): 61
digusur (MB): 2508, rasio 1.06, overhead (%): 1154, counter nundung beurat: 4, ayeuna cache DataBlock (%): 50
digusur (MB): 1824, rasio 1.04, overhead (%): 812, counter nundung beurat: 5, ayeuna cache DataBlock (%): 42
digusur (MB): 1482, rasio 1.03, overhead (%): 641, counter nundung beurat: 6, ayeuna cache DataBlock (%): 36
digusur (MB): 1140, rasio 1.01, overhead (%): 470, counter nundung beurat: 7, ayeuna cache DataBlock (%): 32
digusur (MB): 913, rasio 1.0, overhead (%): 356, counter nundung beurat: 8, ayeuna cache DataBlock (%): 29
digusur (MB): 912, rasio 0.89, overhead (%): 356, counter nundung beurat: 9, ayeuna cache DataBlock (%): 26
digusur (MB): 684, rasio 0.76, overhead (%): 242, counter nundung beurat: 10, ayeuna cache DataBlock (%): 24
digusur (MB): 684, rasio 0.61, overhead (%): 242, counter nundung beurat: 11, ayeuna cache DataBlock (%): 22
digusur (MB): 456, rasio 0.51, overhead (%): 128, counter nundung beurat: 12, ayeuna cache DataBlock (%): 21
digusur (MB): 456, rasio 0.42, overhead (%): 128, counter nundung beurat: 13, ayeuna cache DataBlock (%): 20
digusur (MB): 456, rasio 0.33, overhead (%): 128, counter nundung beurat: 14, ayeuna cache DataBlock (%): 19
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 15, ayeuna cache DataBlock (%): 19
digusur (MB): 342, rasio 0.32, overhead (%): 71, counter nundung beurat: 16, ayeuna cache DataBlock (%): 19
digusur (MB): 342, rasio 0.31, overhead (%): 71, counter nundung beurat: 17, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.3, overhead (%): 14, counter nundung beurat: 18, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.29, overhead (%): 14, counter nundung beurat: 19, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.27, overhead (%): 14, counter nundung beurat: 20, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.25, overhead (%): 14, counter nundung beurat: 21, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.24, overhead (%): 14, counter nundung beurat: 22, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.22, overhead (%): 14, counter nundung beurat: 23, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.21, overhead (%): 14, counter nundung beurat: 24, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.2, overhead (%): 14, counter nundung beurat: 25, ayeuna cache DataBlock (%): 19
digusur (MB): 228, rasio 0.17, overhead (%): 14, counter nundung beurat: 26, ayeuna cache DataBlock (%): 19
digusur (MB): 456, rasio 0.17, overhead (%): 128, counter nundung beurat: 27, ayeuna cache DataBlock (%): 18 <ditambahkeun meunang (tapi tabel sarua)
digusur (MB): 456, rasio 0.15, overhead (%): 128, counter nundung beurat: 28, ayeuna cache DataBlock (%): 17
digusur (MB): 342, rasio 0.13, overhead (%): 71, counter nundung beurat: 29, ayeuna cache DataBlock (%): 17
digusur (MB): 342, rasio 0.11, overhead (%): 71, counter nundung beurat: 30, ayeuna cache DataBlock (%): 17
digusur (MB): 342, rasio 0.09, overhead (%): 71, counter nundung beurat: 31, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.08, overhead (%): 14, counter nundung beurat: 32, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.07, overhead (%): 14, counter nundung beurat: 33, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.06, overhead (%): 14, counter nundung beurat: 34, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.05, overhead (%): 14, counter nundung beurat: 35, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.05, overhead (%): 14, counter nundung beurat: 36, ayeuna cache DataBlock (%): 17
digusur (MB): 228, rasio 0.04, overhead (%): 14, counter nundung beurat: 37, ayeuna cache DataBlock (%): 17
digusur (MB): 109, rasio 0.04, overhead (%): -46, counter nundung beurat: 37, ayeuna cache DataBlock (%): 22 <tekanan deui
digusur (MB): 798, rasio 0.24, overhead (%): 299, counter nundung beurat: 38, ayeuna cache DataBlock (%): 20
digusur (MB): 798, rasio 0.29, overhead (%): 299, counter nundung beurat: 39, ayeuna cache DataBlock (%): 18
digusur (MB): 570, rasio 0.27, overhead (%): 185, counter nundung beurat: 40, ayeuna cache DataBlock (%): 17
digusur (MB): 456, rasio 0.22, overhead (%): 128, counter nundung beurat: 41, ayeuna cache DataBlock (%): 16
digusur (MB): 342, rasio 0.16, overhead (%): 71, counter nundung beurat: 42, ayeuna cache DataBlock (%): 16
digusur (MB): 342, rasio 0.11, overhead (%): 71, counter nundung beurat: 43, ayeuna cache DataBlock (%): 16
digusur (MB): 228, rasio 0.09, overhead (%): 14, counter nundung beurat: 44, ayeuna cache DataBlock (%): 16
digusur (MB): 228, rasio 0.07, overhead (%): 14, counter nundung beurat: 45, ayeuna cache DataBlock (%): 16
digusur (MB): 228, rasio 0.05, overhead (%): 14, counter nundung beurat: 46, ayeuna cache DataBlock (%): 16
digusur (MB): 222, rasio 0.04, overhead (%): 11, counter nundung beurat: 47, ayeuna cache DataBlock (%): 16
digusur (MB): 104, babandingan 0.03, overhead (%): -48, counter nundung beurat: 47, ayeuna cache DataBlock (%): 21 <ngaganggu meunang
digusur (MB): 684, rasio 0.2, overhead (%): 242, counter nundung beurat: 48, ayeuna cache DataBlock (%): 19
digusur (MB): 570, rasio 0.23, overhead (%): 185, counter nundung beurat: 49, ayeuna cache DataBlock (%): 18
digusur (MB): 342, rasio 0.22, overhead (%): 71, counter nundung beurat: 50, ayeuna cache DataBlock (%): 18
digusur (MB): 228, rasio 0.21, overhead (%): 14, counter nundung beurat: 51, ayeuna cache DataBlock (%): 18
digusur (MB): 228, rasio 0.2, overhead (%): 14, counter nundung beurat: 52, ayeuna cache DataBlock (%): 18
digusur (MB): 228, rasio 0.18, overhead (%): 14, counter nundung beurat: 53, ayeuna cache DataBlock (%): 18
digusur (MB): 228, rasio 0.16, overhead (%): 14, counter nundung beurat: 54, ayeuna cache DataBlock (%): 18
digusur (MB): 228, rasio 0.14, overhead (%): 14, counter nundung beurat: 55, ayeuna cache DataBlock (%): 18
digusur (MB): 112, rasio 0.14, overhead (%): -44, counter nundung beurat: 55, ayeuna cache DataBlock (%): 23 <tekanan deui
digusur (MB): 456, rasio 0.26, overhead (%): 128, counter nundung beurat: 56, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.31, overhead (%): 71, counter nundung beurat: 57, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 58, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 59, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 60, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 61, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 62, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 63, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.32, overhead (%): 71, counter nundung beurat: 64, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 65, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 66, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.32, overhead (%): 71, counter nundung beurat: 67, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 68, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.32, overhead (%): 71, counter nundung beurat: 69, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.32, overhead (%): 71, counter nundung beurat: 70, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 71, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 72, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 73, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 74, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 75, ayeuna cache DataBlock (%): 22
digusur (MB): 342, rasio 0.33, overhead (%): 71, counter nundung beurat: 76, ayeuna cache DataBlock (%): 22
digusur (MB): 21, rasio 0.33, overhead (%): -90, counter nundung beurat: 76, ayeuna cache DataBlock (%): 32
digusur (MB): 0, rasio 0.0, overhead (%): -100, counter nundung beurat: 0, ayeuna cache DataBlock (%): 100
digusur (MB): 0, rasio 0.0, overhead (%): -100, counter nundung beurat: 0, ayeuna cache DataBlock (%): 100

Panyeken diperyogikeun pikeun nunjukkeun prosés anu sami dina bentuk grafik hubungan antara dua bagian cache - tunggal (dimana blok anu henteu kantos dipénta sateuacanna) sareng multi (data "dipénta" sahenteuna sakali disimpen di dieu):

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Sarta pamustunganana, naon operasi parameter kasampak kawas dina bentuk grafik. Pikeun babandingan, cache parantos dipareuman di awal, teras HBase diluncurkeun kalayan cache sareng ngalambatkeun ngamimitian karya optimasi ku 5 menit (30 siklus pangusiran).

Kodeu lengkep tiasa dipendakan dina Pull Request HBASE 23887 dina github.

Nanging, 300 rébu maca per detik sanés sadayana anu tiasa dihontal dina hardware ieu dina kaayaan ieu. Kanyataanna nyaéta nalika anjeun kedah ngaksés data liwat HDFS, mékanisme ShortCircuitCache (saterusna disebut SSC) dianggo, anu ngamungkinkeun anjeun ngaksés data sacara langsung, ngahindarkeun interaksi jaringan.

Profiling némbongkeun yén sanajan mékanisme ieu méré gain badag, eta oge di sawatara titik jadi bottleneck, sabab ampir kabéh operasi beurat lumangsung di jero konci, nu ngabalukarkeun blocking lolobana waktu.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Saatos sadar ieu, urang sadar yén masalahna tiasa dileungitkeun ku nyiptakeun sakumpulan SSC anu mandiri:

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

Teras damel sareng aranjeunna, kalebet parapatan ogé dina angka offset anu terakhir:

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

Ayeuna anjeun tiasa ngamimitian nguji. Jang ngalampahkeun ieu, urang bakal maca file tina HDFS kalayan aplikasi multi-threaded basajan. Setel parameter:

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

Sareng ngan ukur maca file:

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

Kode ieu dieksekusi dina threads misah sarta kami baris ngaronjatkeun jumlah sakaligus maca file (tina 10 nepi ka 200 - sumbu horizontal) jeung jumlah caches (tina 1 nepi ka 10 - grafik). Sumbu nangtung nembongkeun akselerasi nu hasil tina paningkatan dina SSC relatif ka kasus lamun aya ngan hiji cache.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Kumaha maca grafik: Waktu palaksanaan pikeun 100 sarébu dibaca dina blok 64 KB sareng hiji cache butuh 78 detik. Sedengkeun kalawan 5 caches butuh 16 detik. Jelema. aya akselerasi ~5 kali. Sapertos tiasa ditingali tina grafik, pangaruhna henteu katingali pisan pikeun sajumlah leutik bacaan paralel, éta mimiti maénkeun peran anu nyata nalika aya langkung ti 50 thread dibaca. sareng di luhur masihan paningkatan kinerja anu langkung alit.

Catetan 1: Kusabab hasil tés rada volatile (tingali di handap), 3 ngajalankeun dilaksanakeun sareng nilai anu hasilna rata-rata.

Catetan 2: Keuntungan kinerja tina konfigurasi aksés acak sarua, sanajan aksés sorangan rada laun.

Nanging, kedah dijelaskeun yén, teu sapertos kasus HBase, akselerasi ieu henteu salawasna gratis. Di dieu urang "muka konci" kamampuan CPU pikeun ngalakukeun padamelan langkung seueur, tibatan ngagantung dina konci.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Di dieu anjeun bisa niténan yén, sacara umum, kanaékan jumlah caches masihan paningkatan kira sabanding dina utilization CPU. Sanajan kitu, aya rada leuwih unggul kombinasi.

Contona, hayu urang nyandak hiji tampilan ngadeukeutan dina setelan SSC = 3. Kanaékan kinerja on rentang nyaeta ngeunaan 3.3 kali. Di handap ieu mangrupakeun hasil tina sakabéh tilu ngalir misah.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Bari konsumsi CPU naek ku ngeunaan 2.8 kali. Bédana henteu ageung pisan, tapi sakedik Greta parantos bagja sareng tiasa gaduh waktos kanggo sakola sareng nyandak pelajaran.

Ku kituna, ieu bakal boga pangaruh positif pikeun sagala alat nu ngagunakeun aksés bulk kana HDFS (contona Spark, jsb), disadiakeun yén kode aplikasi nyaeta lightweight (ie colokan di sisi klien HDFS) jeung aya kakuatan CPU bébas. . Pikeun pariksa, hayu urang nguji naon pangaruh gabungan tina optimasi BlockCache sareng tuning SSC pikeun maca tina HBase bakal gaduh.

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Ieu bisa ditempo yén dina kaayaan kitu pangaruh teu sakumaha hébat sakumaha dina tés refined (maca tanpa processing), tapi ieu rada mungkin mun squeeze kaluar 80K tambahan di dieu. Kalawan babarengan, duanana optimizations nyadiakeun nepi ka 4x speedup.

A PR ogé dijieun pikeun optimasi ieu [HDFS-15202], nu geus dihijikeun jeung pungsi ieu bakal sadia dina release nu bakal datang.

Sarta pamustunganana, éta metot pikeun ngabandingkeun kinerja bacaan tina database lega-kolom sarupa, Cassandra na HBase.

Jang ngalampahkeun ieu, kami ngaluncurkeun conto utilitas uji beban YCSB standar tina dua host (totalna 800 benang). Dina sisi server - 4 instansi RegionServer na Cassandra on 4 host (sanes nu klien nu ngajalankeun, pikeun nyingkahan pangaruh maranéhanana). Bacaan asalna tina tabel ukuran:

HBase - 300 GB dina HDFS (100 GB data murni)

Cassandra - 250 GB (faktor réplikasi = 3)

Jelema. volume éta kira sarua (dina HBase saeutik leuwih).

Parameter HBase:

dfs.client.short.circuit.num = 5 (optimasi klien HDFS)

hbase.lru.cache.heavy.eviction.count.limit = 30 - Ieu ngandung harti yén patch bakal ngamimitian dianggo saatos 30 pangusir (~ 5 menit)

hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - target volume cache sareng pangusir

Log YCSB diuraikan sareng disusun kana grafik Excel:

Kumaha carana ningkatkeun kagancangan maca tina HBase dugi ka 3 kali sareng tina HDFS dugi ka 5 kali

Sakumaha anjeun tiasa tingali, optimasi ieu ngamungkinkeun pikeun ngabandingkeun kinerja database ieu dina kaayaan ieu sarta ngahontal 450 sarébu maca per detik.

Kami ngarepkeun inpormasi ieu tiasa mangfaat pikeun batur salami perjuangan anu pikaresepeun pikeun produktivitas.

sumber: www.habr.com

Tambahkeun komentar