Prestazzjoni għolja hija waħda mir-rekwiżiti ewlenin meta taħdem ma 'big data. Aħna, fil-ġestjoni tat-tagħbija tad-dejta fi Sberbank, qed nippumpjaw kważi t-tranżazzjonijiet kollha fil-Cloud tad-Data tagħna bbażat fuq Hadoop u għalhekk qed nittrattaw flussi ta 'informazzjoni verament kbar. Naturalment, aħna dejjem qed infittxu modi biex intejbu l-prestazzjoni, u issa rridu ngħidulek kif irnexxielna nirranġaw il-klijent RegionServer HBase u HDFS, li għamilha possibbli li tiżdied b'mod sinifikanti l-veloċità tal-operazzjoni tal-qari.
Madankollu, qabel ma ngħaddi għall-essenza tat-titjib, ta 'min jitkellem dwar il-limitazzjonijiet li, fil-prinċipju, ma jistgħux jiġu evitati jekk inti toqgħod fuq l-HDD.
Għaliex l-HDD u l-Qari Fast Random Access Huma Inkompatibbli
Kif tafu, HBase, u ħafna databases oħra, jaħżnu d-dejta fi blokki ta 'diversi għexieren ta' kilobytes fid-daqs. B'mod awtomatiku, dan huwa madwar 64 KB. Issa immaġina li għandna bżonn niksbu biss 100 bytes u nitolbu lil HBase biex tagħtina din id-dejta billi tuża ċerta ċavetta. Peress li d-daqs tal-blokk f'HFiles huwa 64 KB, it-talba se tkun 640 darba akbar (għal minuta!) milli meħtieġ.
Barra minn hekk, peress li t-talba se tgħaddi mill-HDFS u l-mekkaniżmu tal-caching tal-metadejta tagħha ShortCircuitCache (li jippermetti aċċess dirett għall-fajls), allura dan jirriżulta fil-qari diġà 1 MB mid-diska. Madankollu, dan jista 'jiġi aġġustat bil-parametru dfs.client.read.shortcircuit.buffer.size u f'ħafna każijiet jagħmel sens li jitnaqqas dan il-valur, pereżempju għal 126 KB.
Ejja ngħidu li nagħmlu dan, iżda barra minn hekk, meta nibdew naqraw id-dejta permezz tal-java api, b'funzjonijiet bħal FileChannel.read u titlob lis-sistema operattiva biex taqra l-ammont speċifikat ta 'dejta, inaqqas "fil-każ" 2 darbiet aktar , i.e. 256 KB fil-każ tagħna. Dan għaliex m'hemm l-ebda mod faċli f'java biex tissettja l-bandiera FADV_RANDOM biex tevita din l-imġieba.
Bħala riżultat, biex tikseb il-100 bytes tagħna, jinqraw 2600 darba aktar taħt il-barnuża. Jidher li s-soluzzjoni hija ovvja, ejja nnaqqsu d-daqs tal-blokk għal kilobyte, issettja l-bandiera msemmija u niksbu aċċelerazzjoni kbira tal-illuminazzjoni. Iżda l-inkwiet huwa li billi nnaqqsu d-daqs tal-blokk b'2 darbiet, innaqqsu wkoll in-numru ta 'bytes mnaqqsa għal kull unità ta' ħin b'2 darbiet.
Jista' jinkiseb xi gwadann mill-issettjar tal-bandiera FADV_RANDOM, iżda biss b'multithreading għoli u b'daqs tal-blokk ta' 128 KB, iżda dan huwa massimu ta' ftit għexieren ta' fil-mija:
It-testijiet saru fuq 100 fajl, kull 1 GB fid-daqs u li jinsabu fuq 10 HDDs.
Ejja nikkalkulaw fuq xiex nistgħu noqogħdu bażikament b'tali veloċità:
Ejja ngħidu li naqraw minn 10 diski b'veloċità ta '280 MB / s, i.e. 3 miljun darba 100 bytes. Imma kif niftakru, għandna bżonn dejta li hija 2600 darba inqas minn dak li jinqara. Għalhekk, naqsmu 3 miljun b'2600 u nġibu 1100 rekord kull sekonda.
Diżappuntanti, hux? Din hija n-natura Aċċess Każwali aċċess għad-data fuq l-HDD - irrispettivament mid-daqs tal-blokk. Dan huwa l-limitu fiżiku ta 'aċċess każwali u l-ebda database ma tista' tagħfas aktar taħt kundizzjonijiet bħal dawn.
Kif allura jistgħu l-bażijiet jiksbu veloċitajiet ferm ogħla? Biex twieġeb din il-mistoqsija, ejja naraw x'jiġri fl-istampa li ġejja:
Hawnhekk naraw li l-ewwel ftit minuti l-veloċità hija verament madwar elf rekord kull sekonda. Madankollu, barra minn hekk, minħabba l-fatt li jitnaqqas ħafna aktar milli kien mitlub, id-dejta tiġi depożitata fil-buff / cache tas-sistema operattiva (linux) u l-veloċità tikber għal aktar deċenti 60 elf kull sekonda
Għalhekk, aktar se nittrattaw l-aċċess aċċellerat biss għad-dejta li tinsab fil-cache tal-OS jew li tinsab f'apparat ta 'ħażna SSD/NVMe ta' veloċità ta 'aċċess komparabbli.
Fil-każ tagħna, aħna se nwettqu testijiet fuq stand ta '4 servers, li kull wieħed minnhom huwa ċċarġjat kif ġej:
CPU: Xeon E5-2680 v4 @ 2.40GHz 64 ħajt.
Memorja: 730 GB.
verżjoni java: 1.8.0_111
U hawn il-punt ewlieni huwa l-ammont ta 'dejta fit-tabelli li jeħtieġ li jinqara. Il-fatt hu li jekk taqra data minn tabella li tidħol għal kollox fil-cache HBase, allura lanqas biss tasal għall-qari minn buff / cache tas-sistema operattiva. Minħabba li HBase awtomatikament jalloka 40% tal-memorja għal struttura msejħa BlockCache. Fil-fatt, dan huwa ConcurrentHashMap, fejn iċ-ċavetta hija l-isem tal-fajl + offset tal-blokk, u l-valur huwa d-dejta attwali f'dan l-offset.
Għalhekk, meta naqraw biss minn din l-istruttura, aħna
Pereżempju, fil-każ tagħna, il-volum ta 'BlockCache fuq RS wieħed huwa ta' madwar 12 GB. Inżulna żewġ RS fuq nodu wieħed, i.e. 96 GB allokati għal BlockCache fuq in-nodi kollha. U fl-istess ħin, hemm ħafna aktar dejta, pereżempju, ħalliha tkun 4 tabelli, 130 reġjun kull wieħed, li fihom fajls ta 'daqs ta' 800 MB, ikkompressati minn FAST_DIFF, i.e. total ta '410 GB (din hija dejta pura, jiġifieri mingħajr ma jitqies il-fattur ta' replikazzjoni).
Għalhekk, BlockCache huwa biss madwar 23% tad-dejta totali u dan huwa ħafna eqreb tal-kundizzjonijiet reali ta 'dak li jissejjaħ BigData. U hawn jibda l-aktar interessanti - wara kollox, huwa ovvju li inqas ma jkun hemm hits tal-cache, iktar tkun agħar il-prestazzjoni. Wara kollox, f'każ ta' miss, ikollok tagħmel ħafna xogħol - i.e. jinżel qabel issejjaħ il-funzjonijiet tas-sistema. Madankollu, dan ma jistax jiġi evitat, u għalhekk ejja nikkunsidraw aspett kompletament differenti - x'jiġri mid-data ġewwa l-cache?
Ejja nissimplifikaw is-sitwazzjoni u nassumu li għandna cache li fiha jitqiegħed oġġett 1 biss. Hawn eżempju ta’ x’jiġri meta nippruvaw naħdmu b’volum ta’ dejta 3 darbiet akbar mill-cache, ikollna:
1. Poġġi blokk 1 fil-cache
2. Neħħi blokk 1 mill-cache
3. Poġġi blokk 2 fil-cache
4. Neħħi blokk 2 mill-cache
5. Poġġi blokk 3 fil-cache
5 azzjonijiet mitmuma! Madankollu, din is-sitwazzjoni ma tistax tissejjaħ normali; fil-fatt, qed inġegħlu lil HBase tagħmel mazz ta 'xogħol kompletament inutli. Huwa kontinwament jaqra dejta mill-cache tal-OS, ipoġġiha f'BlockCache, biss biex tarmiha kważi immedjatament minħabba li tkun waslet porzjon ġdid ta 'dejta. L-animazzjoni fil-bidu tal-post turi l-essenza tal-problema - Garbage Collector qed imur barra mill-iskala, l-atmosfera qed tissaħħan, iċ-ċkejkna Greta fl-Isvezja mbiegħda u sħuna qed titħawwad. U aħna n-nies tal-IT verament ma nħobbux meta t-tfal ikunu mdejqin, għalhekk nibdew naħsbu dwar x’nistgħu nagħmlu dwaru.
Imma x'jiġri jekk mhux il-blokki kollha jitqiegħdu fil-cache, iżda ċertu persentaġġ minnhom biss, sabiex il-cache ma tfur? Ejja nibdew billi nżidu biss ftit linji ta' kodiċi fil-quċċata tal-funzjoni push BlockCache:
public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {
if (cacheDataBlockPercent != 100 && buf.getBlockType().isData()) {
if (cacheKey.getOffset() % 100 >= cacheDataBlockPercent) {
return;
}
}
...
It-tifsira hawnhekk hija din li ġejja, offset hija l-pożizzjoni tal-blokka fil-fajl u l-aħħar ċifri tagħha huma mqassma b'mod każwali u indaqs minn 00 sa 99. Għalhekk, aħna se naqbżu biss dawk li jaqgħu fil-medda li għandna bżonn.
Pereżempju, issettja cacheDataBlockPercent = 20 u ara x'jiġri:
Ir-riżultat qiegħed hemm. Fil-grafiċi hawn taħt, jidher ċar għaliex seħħet din l-aċċelerazzjoni - aħna niffrankaw mazz ta 'riżorsi GC mingħajr ma nagħmlu x-xogħol ta' Sisyphean li npoġġu d-dejta fil-cache biss biex immedjatament titfagħha fil-fossa fuq il-klieb Martian:
Fl-istess ħin, l-użu tas-CPU jikber, iżda ħafna inqas mill-prestazzjoni:
Ta 'min jinnota wkoll li l-blokki maħżuna fi BlockCache huma differenti. Il-biċċa l-kbira, madwar 95%, hija data nfisha. U l-bqija hija metadata, bħal filtri Bloom jew LEAF_INDEX u
Għalhekk, fil-kodiċi naraw kundizzjoni ta 'kontroll buf.getBlockType().isData() u grazzi għal din il-meta se nżommu fil-cache xorta waħda.
Issa ejja nżidu t-tagħbija u fl-istess ħin tixgħel ftit il-karatteristika. Fl-ewwel test, għamilna l-perċentwal tal-qtugħ = 20 u BlockCache kien daqsxejn mgħobbi biżżejjed. Issa ejja nissettjawha għal 23% u żid 100 ħajt kull 5 minuti biex naraw meta sseħħ is-saturazzjoni:
Hawnhekk naraw li l-verżjoni oriġinali kważi immedjatament tolqot il-limitu ta 'madwar 100 elf talba kull sekonda. Billi l-garża tagħti aċċelerazzjoni sa 300 elf. Fl-istess ħin, huwa ċar li aktar aċċelerazzjoni m'għadhiex daqshekk "ħielsa", filwaqt li l-utilizzazzjoni tas-CPU qed tikber ukoll.
Madankollu, din mhix soluzzjoni eleganti ħafna, peress li ma nafux minn qabel liema perċentwal ta 'blokki għall-cache, jiddependi fuq il-profil tat-tagħbija. Għalhekk, ġie implimentat mekkaniżmu biex jaġġusta awtomatikament dan il-parametru skont l-attività tal-operazzjonijiet tal-qari.
Tliet għażliet ġew miżjuda biex jikkontrollaw dan:
hbase.lru.cache.heavy.eviction.count.limit - tistabbilixxi kemm-il darba l-proċess ta 'tkeċċija tad-dejta mill-cache għandu jibda qabel ma nibdew nużaw l-ottimizzazzjoni (jiġifieri skip blocks). B'mod awtomatiku, huwa ugwali għal MAX_INT = 2147483647 u fil-fatt ifisser li l-karatteristika qatt mhi se tibda taħdem b'dan il-valur. Minħabba li l-proċess ta 'żgumbrament jibda kull 5 - 10 sekondi (jiddependi fuq it-tagħbija) u 2147483647 * 10 / 60 / 60 / 24 / 365 = 680 sena. Madankollu, nistgħu nissettjaw dan il-parametru għal 0 u nagħmlu l-karatteristika taħdem immedjatament wara l-bidu.
Madankollu, hemm ukoll tagħbija f'dan il-parametru. Jekk ikollna n-natura tat-tagħbija b'tali mod li qari għal żmien qasir (ejja ngħidu matul il-jum) u qari fit-tul (bil-lejl) huma kontinwament imxerrda, allura nistgħu nagħmlu l-karatteristika tinxtegħel biss meta operazzjonijiet ta 'qari fit-tul huma fil-progress.
Pereżempju, nafu li l-qari għal żmien qasir normalment idum madwar minuta. M'hemmx bżonn li tibda tarmi l-blokki, il-cache mhux se jkollu ħin biex isir skadut u allura nistgħu nissettjaw dan il-parametru ugwali għal, pereżempju, 1. Dan iwassal għall-fatt li l-ottimizzazzjoni tibda taħdem biss meta twil- il-qari attiv tat-terminu beda, i.e. wara 10 sekonda. Għalhekk, jekk ikollna qari għal żmien qasir, allura l-blokki kollha jidħlu fil-cache u jkunu disponibbli (ħlief għal dawk li se jiġu żgumbrati mill-algoritmu standard). U meta nagħmlu qari fit-tul, il-karatteristika tinxtegħel u jkollna prestazzjoni ferm ogħla.
hbase.lru.cache.heavy.eviction.mb.size.limit - tissettja kemm nixtiequ npoġġu megabytes fil-cache (u naturalment tkeċċi) f'10 sekondi. Il-karatteristika se tipprova tilħaq dan il-valur u żżommu. Il-punt huwa dan: jekk nidħlu gigabytes fil-cache, allura jkollna nkeċċu gigabytes, u dan, kif rajna hawn fuq, jiswa ħafna flus. Madankollu, m'għandekx tipprova tissettjaha żgħira wisq, peress li dan iwassal għal ħruġ prematur mill-mod ta 'jaqbeż il-blokk. Għal servers b'saħħithom (madwar 20-40 qlub fiżiċi), huwa ottimali li jiġu stabbiliti madwar 300-400 MB. Għall-klassi tan-nofs (~ 10 cores) 200-300 MB. Għal sistemi dgħajfa (2-5 qlub) 50-100 MB jistgħu jkunu normali (mhux ittestjati fuq dawn).
Ejja nħarsu lejn kif jaħdem dan: ejja ngħidu li nissettjaw hbase.lru.cache.heavy.eviction.mb.size.limit = 500, hemm xi tip ta' tagħbija (qari) u mbagħad kull ~10 sekondi nikkalkulaw kemm kien hemm bytes żgumbrat bl-użu tal-formula:
Overhead = Somm ta' Bytes Meħlusa (MB) * 100 / Limitu (MB) - 100;
Jekk fil-fatt 2000 MB ġew żgumbrati, allura Overhead hija ugwali għal:
2000 * 100 / 500 - 100 = 300%
L-algoritmi jippruvaw jappoġġjaw mhux aktar minn ftit għexieren ta 'mija, għalhekk il-karatteristika tnaqqas il-perċentwal ta' blokki fil-cache, u b'hekk timplimenta l-mekkaniżmu ta 'rfinar awtomatiku.
Madankollu, jekk it-tagħbija tinżel, ejja ngħidu li 200 MB biss jiġu żgumbrati u Overhead isir negattiv (l-hekk imsejjaħ overshooting):
200 * 100 / 500 - 100 = -60%
Għall-kuntrarju, il-karatteristika se żżid il-persentaġġ ta 'blokki fil-cache sakemm Overhead isir pożittiv.
Hawn taħt hemm eżempju ta 'kif dan jidher fuq data reali. M'hemmx bżonn li tipprova tilħaq 0%, huwa impossibbli. Huwa tajjeb ħafna meta jkun ta 'madwar 30 - 100%, dan jgħin biex jiġi evitat ħruġ prematur mill-mod ta' ottimizzazzjoni waqt żidiet f'terminu qasir.
hbase.lru.cache.heavy.eviction.overhead.coefficient - tistabbilixxi kemm nixtiequ nġibu r-riżultat malajr. Jekk nafu żgur li l-qari tagħna huma l-aktar twal u ma rridux nistennew, nistgħu nżidu dan il-proporzjon u niksbu prestazzjoni għolja aktar malajr.
Pereżempju, aħna nissettjaw dan il-koeffiċjent = 0.01. Dan ifisser li Overhead (ara hawn fuq) se jiġi mmultiplikat b'dan in-numru bir-riżultat u l-perċentwal ta 'blokki cache se jitnaqqas. Ejja ngħidu li Overhead = 300%, u l-koeffiċjent = 0.01, allura l-persentaġġ ta 'blokki cache se jitnaqqas bi 3%.
Loġika simili ta '"Kontropressjoni" hija implimentata wkoll għal valuri negattivi ta' Overhead (overshooting). Peress li l-varjazzjonijiet għal żmien qasir fil-volum ta 'qari u żgumbramenti huma dejjem possibbli, dan il-mekkaniżmu jippermettilek tevita ħruġ prematur mill-mod ta' ottimizzazzjoni. Il-kontropressjoni għandha loġika maqluba: iktar ma tkun b'saħħitha l-overshooting, aktar blokki jiġu miżmumin fil-cache.
Kodiċi ta' implimentazzjoni
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;
}
Ikkunsidra issa dan kollu fuq eżempju reali. Għandna x-xenarju tat-test li ġej:
- Ibda tagħmel Scan (25 ħajta, lott = 100)
- Wara 5 minuti, żid multi-gets (25 ħajta, lott = 100)
- Wara 5 minuti, itfi l-multi-gets (reġa' jibqa' biss scan)
Nagħmlu żewġ ġirjiet, l-ewwel hbase.lru.cache.heavy.eviction.count.limit = 10000 (li fil-fatt tiddiżattiva l-karatteristika), u mbagħad issettja limitu = 0 (jippermetti).
Fir-zkuk hawn taħt naraw kif il-karatteristika tinxtegħel u tirreset Overshooting għal 14-71%. Minn żmien għal żmien it-tagħbija tinżel, li tixgħel il-Backpressure u l-HBase jaqbad aktar blokki mill-ġdid.
Log tar-Reġjun Server
żgumbrat (MB): 0, proporzjon 0.0, overhead (%): -100, counter ta 'żgumbrament tqil: 0, caching kurrenti DataBlock (%): 100
żgumbrat (MB): 0, proporzjon 0.0, overhead (%): -100, counter ta 'żgumbrament tqil: 0, caching kurrenti DataBlock (%): 100
żgumbrat (MB): 2170, proporzjon 1.09, overhead (%): 985, counter ta 'żgumbrament tqil: 1, caching kurrenti DataBlock (%): 91 < bidu
żgumbrat (MB): 3763, proporzjon 1.08, overhead (%): 1781, counter ta 'żgumbrament tqil: 2, caching kurrenti DataBlock (%): 76
żgumbrat (MB): 3306, proporzjon 1.07, overhead (%): 1553, counter ta 'żgumbrament tqil: 3, caching kurrenti DataBlock (%): 61
żgumbrat (MB): 2508, proporzjon 1.06, overhead (%): 1154, counter ta 'żgumbrament tqil: 4, caching kurrenti DataBlock (%): 50
żgumbrat (MB): 1824, proporzjon 1.04, overhead (%): 812, counter ta 'żgumbrament tqil: 5, caching kurrenti DataBlock (%): 42
żgumbrat (MB): 1482, proporzjon 1.03, overhead (%): 641, counter ta 'żgumbrament tqil: 6, caching kurrenti DataBlock (%): 36
żgumbrat (MB): 1140, proporzjon 1.01, overhead (%): 470, counter ta 'żgumbrament tqil: 7, caching kurrenti DataBlock (%): 32
żgumbrat (MB): 913, proporzjon 1.0, overhead (%): 356, counter ta 'żgumbrament tqil: 8, caching kurrenti DataBlock (%): 29
żgumbrat (MB): 912, proporzjon 0.89, overhead (%): 356, counter ta 'żgumbrament tqil: 9, caching kurrenti DataBlock (%): 26
żgumbrat (MB): 684, proporzjon 0.76, overhead (%): 242, counter ta 'żgumbrament tqil: 10, caching kurrenti DataBlock (%): 24
żgumbrat (MB): 684, proporzjon 0.61, overhead (%): 242, counter ta 'żgumbrament tqil: 11, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 456, proporzjon 0.51, overhead (%): 128, counter ta 'żgumbrament tqil: 12, caching kurrenti DataBlock (%): 21
żgumbrat (MB): 456, proporzjon 0.42, overhead (%): 128, counter ta 'żgumbrament tqil: 13, caching kurrenti DataBlock (%): 20
żgumbrat (MB): 456, proporzjon 0.33, overhead (%): 128, counter ta 'żgumbrament tqil: 14, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 15, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 342, proporzjon 0.32, overhead (%): 71, counter ta 'żgumbrament tqil: 16, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 342, proporzjon 0.31, overhead (%): 71, counter ta 'żgumbrament tqil: 17, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.3, overhead (%): 14, counter ta 'żgumbrament tqil: 18, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.29, overhead (%): 14, counter ta 'żgumbrament tqil: 19, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.27, overhead (%): 14, counter ta 'żgumbrament tqil: 20, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.25, overhead (%): 14, counter ta 'żgumbrament tqil: 21, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.24, overhead (%): 14, counter ta 'żgumbrament tqil: 22, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.22, overhead (%): 14, counter ta 'żgumbrament tqil: 23, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.21, overhead (%): 14, counter ta 'żgumbrament tqil: 24, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.2, overhead (%): 14, counter ta 'żgumbrament tqil: 25, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 228, proporzjon 0.17, overhead (%): 14, counter ta 'żgumbrament tqil: 26, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 456, proporzjon 0.17, overhead (%): 128, counter ta 'żgumbrament tqil: 27, caching kurrenti DataBlock (%): 18 < miżjud gets (iżda tabella l-istess)
żgumbrat (MB): 456, proporzjon 0.15, overhead (%): 128, counter ta 'żgumbrament tqil: 28, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 342, proporzjon 0.13, overhead (%): 71, counter ta 'żgumbrament tqil: 29, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 342, proporzjon 0.11, overhead (%): 71, counter ta 'żgumbrament tqil: 30, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 342, proporzjon 0.09, overhead (%): 71, counter ta 'żgumbrament tqil: 31, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.08, overhead (%): 14, counter ta 'żgumbrament tqil: 32, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.07, overhead (%): 14, counter ta 'żgumbrament tqil: 33, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.06, overhead (%): 14, counter ta 'żgumbrament tqil: 34, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.05, overhead (%): 14, counter ta 'żgumbrament tqil: 35, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.05, overhead (%): 14, counter ta 'żgumbrament tqil: 36, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 228, proporzjon 0.04, overhead (%): 14, counter ta 'żgumbrament tqil: 37, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 109, proporzjon 0.04, overhead (%): -46, counter ta 'żgumbrament tqil: 37, caching kurrenti DataBlock (%): 22 < pressjoni lura
żgumbrat (MB): 798, proporzjon 0.24, overhead (%): 299, counter ta 'żgumbrament tqil: 38, caching kurrenti DataBlock (%): 20
żgumbrat (MB): 798, proporzjon 0.29, overhead (%): 299, counter ta 'żgumbrament tqil: 39, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 570, proporzjon 0.27, overhead (%): 185, counter ta 'żgumbrament tqil: 40, caching kurrenti DataBlock (%): 17
żgumbrat (MB): 456, proporzjon 0.22, overhead (%): 128, counter ta 'żgumbrament tqil: 41, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 342, proporzjon 0.16, overhead (%): 71, counter ta 'żgumbrament tqil: 42, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 342, proporzjon 0.11, overhead (%): 71, counter ta 'żgumbrament tqil: 43, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 228, proporzjon 0.09, overhead (%): 14, counter ta 'żgumbrament tqil: 44, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 228, proporzjon 0.07, overhead (%): 14, counter ta 'żgumbrament tqil: 45, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 228, proporzjon 0.05, overhead (%): 14, counter ta 'żgumbrament tqil: 46, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 222, proporzjon 0.04, overhead (%): 11, counter ta 'żgumbrament tqil: 47, caching kurrenti DataBlock (%): 16
żgumbrat (MB): 104, proporzjon 0.03, overhead (%): -48, counter ta 'żgumbrament tqil: 47, caching kurrenti DataBlock (%): 21 < interrupt gets
żgumbrat (MB): 684, proporzjon 0.2, overhead (%): 242, counter ta 'żgumbrament tqil: 48, caching kurrenti DataBlock (%): 19
żgumbrat (MB): 570, proporzjon 0.23, overhead (%): 185, counter ta 'żgumbrament tqil: 49, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 342, proporzjon 0.22, overhead (%): 71, counter ta 'żgumbrament tqil: 50, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 228, proporzjon 0.21, overhead (%): 14, counter ta 'żgumbrament tqil: 51, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 228, proporzjon 0.2, overhead (%): 14, counter ta 'żgumbrament tqil: 52, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 228, proporzjon 0.18, overhead (%): 14, counter ta 'żgumbrament tqil: 53, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 228, proporzjon 0.16, overhead (%): 14, counter ta 'żgumbrament tqil: 54, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 228, proporzjon 0.14, overhead (%): 14, counter ta 'żgumbrament tqil: 55, caching kurrenti DataBlock (%): 18
żgumbrat (MB): 112, proporzjon 0.14, overhead (%): -44, counter ta 'żgumbrament tqil: 55, caching kurrenti DataBlock (%): 23 < pressjoni lura
żgumbrat (MB): 456, proporzjon 0.26, overhead (%): 128, counter ta 'żgumbrament tqil: 56, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.31, overhead (%): 71, counter ta 'żgumbrament tqil: 57, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 58, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 59, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 60, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 61, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 62, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 63, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.32, overhead (%): 71, counter ta 'żgumbrament tqil: 64, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 65, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 66, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.32, overhead (%): 71, counter ta 'żgumbrament tqil: 67, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 68, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.32, overhead (%): 71, counter ta 'żgumbrament tqil: 69, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.32, overhead (%): 71, counter ta 'żgumbrament tqil: 70, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 71, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 72, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 73, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 74, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 75, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 342, proporzjon 0.33, overhead (%): 71, counter ta 'żgumbrament tqil: 76, caching kurrenti DataBlock (%): 22
żgumbrat (MB): 21, proporzjon 0.33, overhead (%): -90, counter ta 'żgumbrament tqil: 76, caching kurrenti DataBlock (%): 32
żgumbrat (MB): 0, proporzjon 0.0, overhead (%): -100, counter ta 'żgumbrament tqil: 0, caching kurrenti DataBlock (%): 100
żgumbrat (MB): 0, proporzjon 0.0, overhead (%): -100, counter ta 'żgumbrament tqil: 0, caching kurrenti DataBlock (%): 100
L-iskans kienu meħtieġa sabiex juru l-istess proċess fil-forma ta 'graff tar-relazzjoni bejn żewġ sezzjonijiet tal-cache - single (fejn blokki li ħadd qatt ma talab s'issa) u multi (id-data "rikjesta" mill-inqas darba huma maħżuna hawn):
U fl-aħħarnett, kif tidher l-operazzjoni tal-parametri fil-forma ta 'graff. Għal tqabbil, il-cache kienet mitfija kompletament fil-bidu, imbagħad HBase tnediet b'caching u ttardja l-bidu tax-xogħol ta 'ottimizzazzjoni b'5 minuti (30 ċiklu ta' żgumbrament).
Il-kodiċi sħiħ jista' jinstab f'Pull Request
Madankollu, 300 elf qari kull sekonda mhuwiex dak kollu li jista 'jingħafas fuq dan il-hardware taħt dawn il-kundizzjonijiet. Il-fatt hu li meta jkollok bżonn taċċessa d-dejta permezz tal-HDFS, jintuża l-mekkaniżmu ShortCircuitCache (minn hawn 'il quddiem SSC), li jippermettilek taċċessa d-dejta direttament, u tevita l-interazzjonijiet tan-netwerk.
Il-profiling wera li għalkemm dan il-mekkaniżmu jagħti gwadann kbir, isir ukoll ostaklu f'xi punt, minħabba li kważi l-operazzjonijiet tqal kollha jseħħu ġewwa l-lock, li jwassal għal serraturi ħafna mill-ħin.
Meta rrealizzajna dan, indunajna li l-problema tista 'tiġi evitata billi noħolqu firxa ta' SSCs indipendenti:
private final ShortCircuitCache[] shortCircuitCache;
...
shortCircuitCache = new ShortCircuitCache[this.clientShortCircuitNum];
for (int i = 0; i < this.clientShortCircuitNum; i++)
this.shortCircuitCache[i] = new ShortCircuitCache(…);
U mbagħad aħdem magħhom, esklużi l-intersezzjonijiet ukoll bl-aħħar ċifra tal-offset:
public ShortCircuitCache getShortCircuitCache(long idx) {
return shortCircuitCache[(int) (idx % clientShortCircuitNum)];
}
Issa tista 'tibda tittestja. Biex tagħmel dan, aħna se naqraw fajls minn HDFS b'applikazzjoni sempliċi b'ħafna kamini. Issettja l-parametri:
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
U aqra biss il-fajls:
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);
}
Dan il-kodiċi jiġi esegwit f'ħjut separati u se nżidu n-numru ta 'fajls li jinqraw simultanjament (minn 10 għal 200 - l-assi orizzontali) u n-numru ta' caches (minn 1 sa 10 - grafika). L-assi vertikali juri l-aċċelerazzjoni li ż-żieda fl-SSC tagħti relattiva għall-każ meta jkun hemm cache waħda biss.
Kif taqra l-graff: 100k jaqra fi blokki 64K b'cache waħda tieħu 78 sekonda biex titlesta. Billi b'5 caches tieħu 16-il sekonda. Dawk. hemm aċċelerazzjoni ta '~5 darbiet. Kif tista 'tara mill-graff, fuq numru żgħir ta' qari paralleli, l-effett mhux notevoli ħafna, jibda jkollu rwol notevoli meta l-qari tal-ħajta huma aktar minn 50. Huwa wkoll notevoli li jiżdied in-numru ta 'SSCs minn 6 u 'l fuq jagħti gwadann ta' prestazzjoni ferm inqas.
Nota 1: peress li r-riżultati tat-test huma pjuttost volatili (ara hawn taħt), twettqu 3 tnedijiet u l-valuri miksuba ġew medjati.
Nota 2: Il-gwadann tal-prestazzjoni mill-issettjar tal-aċċess każwali huwa l-istess, għalkemm l-aċċess innifsu huwa kemmxejn aktar bil-mod.
Madankollu, għandu jiġi ċċarat li, b'differenza mill-każ b'HBase, din l-aċċelerazzjoni mhux dejjem hija ħielsa. Hawnhekk aħna aktar "nitilfu" l-abbiltà tas-CPU biex jagħmlu xogħol, minflok mdendlin fuq serraturi.
Hawnhekk tista 'tara li b'mod ġenerali, żieda fin-numru ta' caches tagħti żieda bejn wieħed u ieħor proporzjonali fl-utilizzazzjoni tas-CPU. Madankollu, hemm kemmxejn aktar kombinazzjonijiet rebbieħa.
Pereżempju, ejja nagħtu ħarsa aktar mill-qrib lejn l-issettjar SSC = 3. Iż-żieda fil-prestazzjoni fuq il-medda hija madwar 3.3 darbiet. Hawn taħt jinsabu r-riżultati tat-tliet ġirjiet separati kollha.
Billi l-konsum tas-CPU jikber b'madwar 2.8 darbiet. Id-differenza mhix kbira ħafna, imma ċ-ċkejkna Greta diġà hi kuntenta u forsi jkun hemm ħin biex tattendi l-iskola u l-lezzjonijiet.
Għalhekk, dan ikollu effett pożittiv fuq kwalunkwe għodda li tuża aċċess bl-ingrossa HDFS (per eżempju, Spark, eċċ.), sakemm il-kodiċi tal-applikazzjoni jkun ħafif (jiġifieri twaħħalha fuq in-naħa tal-klijent HDFS) u jkun hemm qawwa CPU b'xejn. Biex tiċċekkja, ejja nittestjaw x'effett se jagħti l-użu kkombinat tal-ottimizzazzjoni u l-irfinar ta 'SSC ta' BlockCache biex jinqara minn HBase.
Wieħed jista 'jara li taħt kundizzjonijiet bħal dawn l-effett mhuwiex kbir daqs f'testijiet raffinati (qari mingħajr ebda ipproċessar), iżda huwa pjuttost possibbli li jingħafsu 80K addizzjonali hawn. Flimkien, iż-żewġ ottimizzazzjonijiet jipprovdu veloċità sa 4x.
Sar ukoll PR għal din l-ottimizzazzjoni
U fl-aħħarnett, kien interessanti li titqabbel il-prestazzjoni tal-qari ta 'database ta' kolonna wiesgħa simili, Cassandra u HBase.
Biex tagħmel dan, ġew imnedija każijiet tal-utilità standard tal-ittestjar tat-tagħbija YCSB minn żewġ hosts (800 ħajt b'kollox). Fuq in-naħa tas-server - 4 każijiet ta’ RegionServer u Cassandra fuq 4 hosts (mhux fejn il-klijenti qed jaħdmu biex jevitaw l-influwenza tagħhom). Il-qari ġie minn tabelli tad-daqs:
HBase - 300 GB fuq HDFS (100 GB dejta mhux ipproċessata)
Cassandra - 250 GB (fattur ta 'replikazzjoni = 3)
Dawk. il-volum kien bejn wieħed u ieħor l-istess (f'HBase ftit aktar).
Għażliet Hbase:
dfs.client.short.circuit.num = 5 (Ottimizzazzjoni tal-klijent HDFS)
hbase.lru.cache.heavy.eviction.count.limit = 30 - dan ifisser li l-garża se tibda taħdem wara 30 żgumbrament (~5 minuti)
hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - volum mira ta' caching u żgumbrament
Iċ-zkuk tal-YCSB ġew analizzati u kkompilati fi graphs Excel:
Kif tistgħu taraw, id-dejta tal-ottimizzazzjoni tagħmilha possibbli li tiġi ugwalizzata l-prestazzjoni ta 'dawn id-databases taħt dawn il-kundizzjonijiet u tikseb 450 qari kull sekonda.
Nittamaw li din l-informazzjoni tista 'tkun utli għal xi ħadd fil-kors ta' ġlieda eċċitanti għall-prestazzjoni.
Sors: www.habr.com