HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

મોટા ડેટા સાથે કામ કરતી વખતે ઉચ્ચ પ્રદર્શન એ મુખ્ય આવશ્યકતાઓમાંની એક છે. Sberbank ખાતે ડેટા લોડિંગ વિભાગમાં, અમે લગભગ તમામ વ્યવહારો અમારા Hadoop-આધારિત ડેટા ક્લાઉડમાં પમ્પ કરીએ છીએ અને તેથી માહિતીના ખરેખર મોટા પ્રવાહ સાથે વ્યવહાર કરીએ છીએ. સ્વાભાવિક રીતે, અમે હંમેશા કામગીરી બહેતર બનાવવાની રીતો શોધીએ છીએ, અને હવે અમે તમને જણાવવા માંગીએ છીએ કે અમે કેવી રીતે RegionServer HBase અને HDFS ક્લાયંટને પેચ કરવામાં વ્યવસ્થાપિત થયા, જેના કારણે અમે વાંચવાની કામગીરીની ઝડપને નોંધપાત્ર રીતે વધારવામાં સક્ષમ થયા.
HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

જો કે, સુધારણાઓના સારમાં આગળ વધતા પહેલા, તે પ્રતિબંધો વિશે વાત કરવી યોગ્ય છે જે, સૈદ્ધાંતિક રીતે, જો તમે એચડીડી પર બેસો તો તેને ટાળી શકાશે નહીં.

શા માટે HDD અને ઝડપી રેન્ડમ એક્સેસ રીડ અસંગત છે
જેમ તમે જાણો છો, HBase અને અન્ય ઘણા ડેટાબેઝ, ઘણા દસ કિલોબાઈટના કદના બ્લોકમાં ડેટા સ્ટોર કરે છે. મૂળભૂત રીતે તે લગભગ 64 KB છે. હવે ચાલો કલ્પના કરીએ કે આપણે માત્ર 100 બાઈટ મેળવવાની જરૂર છે અને અમે HBase ને ચોક્કસ કીનો ઉપયોગ કરીને આ ડેટા આપવા માટે કહીએ છીએ. HFiles માં બ્લોકનું કદ 64 KB હોવાથી, વિનંતી જરૂરી કરતાં 640 ગણી મોટી (ફક્ત એક મિનિટ!) ​​હશે.

આગળ, કારણ કે વિનંતી HDFS અને તેના મેટાડેટા કેશીંગ મિકેનિઝમમાંથી પસાર થશે શોર્ટ સર્કિટ કેશ (જે ફાઇલોને સીધી ઍક્સેસની મંજૂરી આપે છે), આ ડિસ્કમાંથી પહેલેથી જ 1 MB વાંચવા તરફ દોરી જાય છે. જો કે, આ પરિમાણ સાથે ગોઠવી શકાય છે dfs.client.read.shortcircuit.buffer.size અને ઘણા કિસ્સાઓમાં આ મૂલ્ય ઘટાડવાનો અર્થ થાય છે, ઉદાહરણ તરીકે 126 KB.

ચાલો કહીએ કે અમે આ કરીએ છીએ, પરંતુ વધુમાં, જ્યારે આપણે જાવા એપીઆઈ દ્વારા ડેટા વાંચવાનું શરૂ કરીએ છીએ, જેમ કે FileChannel.read જેવા ફંક્શન અને ઑપરેટિંગ સિસ્ટમને ઉલ્લેખિત ડેટા વાંચવા માટે કહીએ છીએ, તે "માત્ર કિસ્સામાં" 2 ગણું વધુ વાંચે છે. , એટલે કે અમારા કિસ્સામાં 256 KB. આ એટલા માટે છે કારણ કે જાવા પાસે આ વર્તનને રોકવા માટે FADV_RANDOM ફ્લેગ સેટ કરવાની સરળ રીત નથી.

પરિણામે, અમારા 100 બાઇટ્સ મેળવવા માટે, હૂડ હેઠળ 2600 ગણું વધુ વાંચવામાં આવે છે. એવું લાગે છે કે ઉકેલ સ્પષ્ટ છે, ચાલો બ્લોકનું કદ એક કિલોબાઈટ સુધી ઘટાડીએ, ઉલ્લેખિત ધ્વજ સેટ કરીએ અને મહાન જ્ઞાન પ્રવેગક પ્રાપ્ત કરીએ. પરંતુ મુશ્કેલી એ છે કે બ્લોકનું કદ 2 ગણું ઘટાડીને, અમે સમયના એકમ દીઠ વાંચેલા બાઈટની સંખ્યા પણ 2 ગણી ઓછી કરીએ છીએ.

FADV_RANDOM ફ્લેગ સેટ કરવાથી થોડો ફાયદો મેળવી શકાય છે, પરંતુ માત્ર ઉચ્ચ મલ્ટિ-થ્રેડીંગ અને 128 KB ના બ્લોક સાઇઝ સાથે, પરંતુ આ વધુમાં વધુ દસ ટકા છે:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

100 ફાઇલો પર પરીક્ષણો હાથ ધરવામાં આવ્યા હતા, દરેક 1 GB ની સાઇઝની અને 10 HDD પર સ્થિત છે.

ચાલો ગણતરી કરીએ કે આપણે શું કરી શકીએ છીએ, સૈદ્ધાંતિક રીતે, આ ઝડપ પર ગણતરી કરીએ:
ચાલો કહીએ કે આપણે 10 ડિસ્કમાંથી 280 એમબી/સેકંડની ઝડપે વાંચીએ છીએ, એટલે કે. 3 મિલિયન વખત 100 બાઇટ્સ. પરંતુ જેમ આપણે યાદ રાખીએ છીએ, આપણને જે ડેટાની જરૂર છે તે વાંચેલા ડેટા કરતા 2600 ગણો ઓછો છે. આમ, આપણે 3 મિલિયનને 2600 વડે ભાગીએ છીએ અને મેળવીએ છીએ 1100 રેકોર્ડ પ્રતિ સેકન્ડ.

હતાશાજનક, તે નથી? તે પ્રકૃતિ છે રેન્ડમ એક્સેસ HDD પર ડેટાની ઍક્સેસ - બ્લોક કદને ધ્યાનમાં લીધા વિના. આ રેન્ડમ એક્સેસની ભૌતિક મર્યાદા છે અને આવી પરિસ્થિતિઓમાં કોઈ ડેટાબેઝ વધુ સ્ક્વિઝ કરી શકતું નથી.

તો પછી ડેટાબેઝ કેવી રીતે વધુ ઝડપ પ્રાપ્ત કરે છે? આ પ્રશ્નનો જવાબ આપવા માટે, ચાલો જોઈએ કે નીચેના ચિત્રમાં શું થઈ રહ્યું છે:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

અહીં આપણે જોઈએ છીએ કે પ્રથમ થોડી મિનિટો માટે ઝડપ ખરેખર એક હજાર રેકોર્ડ પ્રતિ સેકન્ડ જેટલી છે. જો કે, આગળ, એ હકીકતને કારણે કે વિનંતી કરવામાં આવી હતી તેના કરતાં ઘણું વધારે વાંચવામાં આવ્યું હતું, ડેટા ઓપરેટિંગ સિસ્ટમ (લિનક્સ) ના બફ/કેશમાં સમાપ્ત થાય છે અને ઝડપ વધુ યોગ્ય 60 હજાર પ્રતિ સેકન્ડ સુધી વધે છે.

આમ, આગળ અમે ફક્ત OS કેશમાં હોય અથવા તુલનાત્મક એક્સેસ સ્પીડના SSD/NVMe સ્ટોરેજ ઉપકરણોમાં સ્થિત ડેટાની એક્સિલરેટીંગ એક્સેસ સાથે વ્યવહાર કરીશું.

અમારા કિસ્સામાં, અમે 4 સર્વરની બેન્ચ પર પરીક્ષણો હાથ ધરીશું, જેમાંથી દરેક નીચે મુજબ ચાર્જ કરવામાં આવે છે:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 થ્રેડો.
મેમરી: 730 જીબી.
java સંસ્કરણ: 1.8.0_111

અને અહીં મુખ્ય મુદ્દો એ કોષ્ટકોમાં ડેટાની માત્રા છે જેને વાંચવાની જરૂર છે. હકીકત એ છે કે જો તમે ટેબલમાંથી ડેટા વાંચો છો જે સંપૂર્ણપણે HBase કેશમાં મૂકવામાં આવે છે, તો તે ઑપરેટિંગ સિસ્ટમના બફ/કેશમાંથી વાંચવામાં પણ આવશે નહીં. કારણ કે HBase મૂળભૂત રીતે 40% મેમરી બ્લોકકેચ નામના સ્ટ્રક્ચરને ફાળવે છે. અનિવાર્યપણે આ એક સમવર્તી હેશમેપ છે, જ્યાં કી એ બ્લોકનું ફાઇલ નામ + ઑફસેટ છે, અને મૂલ્ય આ ઑફસેટ પરનો વાસ્તવિક ડેટા છે.

આમ, જ્યારે ફક્ત આ રચનામાંથી વાંચીએ છીએ, ત્યારે આપણે અમે ઉત્તમ ઝડપ જોઈ, જેમ કે પ્રતિ સેકન્ડમાં એક મિલિયન વિનંતીઓ. પરંતુ ચાલો કલ્પના કરીએ કે આપણે ફક્ત ડેટાબેઝની જરૂરિયાતો માટે સેંકડો ગીગાબાઇટ્સ મેમરી ફાળવી શકતા નથી, કારણ કે આ સર્વર્સ પર બીજી ઘણી ઉપયોગી વસ્તુઓ ચાલી રહી છે.

ઉદાહરણ તરીકે, અમારા કિસ્સામાં, એક આરએસ પર બ્લોકકેશનું વોલ્યુમ લગભગ 12 જીબી છે. અમે એક નોડ પર બે RS ઉતર્યા, એટલે કે. તમામ નોડ્સ પર બ્લોકકેશ માટે 96 GB ફાળવવામાં આવ્યા છે. અને ત્યાં અનેક ગણો વધુ ડેટા છે, ઉદાહરણ તરીકે, તેને 4 કોષ્ટકો, પ્રત્યેક 130 પ્રદેશો, જેમાં ફાઇલો 800 MB કદની છે, FAST_DIFF દ્વારા સંકુચિત છે, એટલે કે. કુલ 410 GB (આ શુદ્ધ ડેટા છે, એટલે કે પ્રતિકૃતિ પરિબળને ધ્યાનમાં લીધા વિના).

આમ, BlockCache એ કુલ ડેટા વોલ્યુમના માત્ર 23% જેટલો છે અને આ બિગડેટા કહેવાતી વાસ્તવિક પરિસ્થિતિઓની ઘણી નજીક છે. અને આ તે છે જ્યાં આનંદ શરૂ થાય છે - કારણ કે દેખીતી રીતે, ઓછા કેશ હિટ, પ્રદર્શન વધુ ખરાબ. છેવટે, જો તમે ચૂકી જાઓ છો, તો તમારે ઘણું કામ કરવું પડશે - એટલે કે. કૉલિંગ સિસ્ટમ ફંક્શન પર નીચે જાઓ. જો કે, આ ટાળી શકાતું નથી, તેથી ચાલો એક સંપૂર્ણપણે અલગ પાસું જોઈએ - કેશની અંદરના ડેટાનું શું થાય છે?

ચાલો પરિસ્થિતિને સરળ બનાવીએ અને ધારીએ કે અમારી પાસે એક કેશ છે જે ફક્ત 1 ઑબ્જેક્ટને બંધબેસે છે. જ્યારે આપણે કેશ કરતા 3 ગણા મોટા ડેટા વોલ્યુમ સાથે કામ કરવાનો પ્રયાસ કરીશું ત્યારે શું થશે તેનું ઉદાહરણ અહીં છે, અમારે આ કરવું પડશે:

1. કેશમાં બ્લોક 1 મૂકો
2. કેશમાંથી બ્લોક 1 દૂર કરો
3. કેશમાં બ્લોક 2 મૂકો
4. કેશમાંથી બ્લોક 2 દૂર કરો
5. કેશમાં બ્લોક 3 મૂકો

5 ક્રિયાઓ પૂર્ણ થઈ! જો કે, આ સ્થિતિને સામાન્ય કહી શકાય નહીં; વાસ્તવમાં, અમે HBase ને સંપૂર્ણપણે નકામું કામ કરવા દબાણ કરી રહ્યા છીએ. તે સતત OS કેશમાંથી ડેટા વાંચે છે, તેને BlockCache માં મૂકે છે, માત્ર તેને લગભગ તરત જ બહાર ફેંકવા માટે કારણ કે ડેટાનો નવો ભાગ આવી ગયો છે. પોસ્ટની શરૂઆતમાં એનિમેશન સમસ્યાનો સાર બતાવે છે - ગાર્બેજ કલેક્ટર સ્કેલ બંધ થઈ રહ્યું છે, વાતાવરણ ગરમ થઈ રહ્યું છે, દૂરની અને ગરમ સ્વીડનમાં નાની ગ્રેટા અસ્વસ્થ થઈ રહી છે. અને જ્યારે બાળકો ઉદાસ હોય ત્યારે અમે IT લોકોને તે ખરેખર ગમતું નથી, તેથી અમે તેના વિશે શું કરી શકીએ તે વિશે વિચારવાનું શરૂ કરીએ છીએ.

જો તમે કેશમાં બધા બ્લોક્સ ન મૂકશો, પરંતુ તેમાંથી માત્ર અમુક ટકાવારી કરો છો, જેથી કેશ ઓવરફ્લો ન થાય? ચાલો BlockCache માં ડેટા મૂકવા માટે ફંક્શનની શરૂઆતમાં કોડની માત્ર થોડી લીટીઓ ઉમેરીને શરૂઆત કરીએ:

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

અહીંનો મુદ્દો નીચે મુજબ છે: ઑફસેટ એ ફાઇલમાં બ્લોકની સ્થિતિ છે અને તેના છેલ્લા અંકો 00 થી 99 સુધી અવ્યવસ્થિત અને સમાનરૂપે વિતરિત કરવામાં આવે છે. તેથી, અમે ફક્ત તે જ છોડીશું જે અમને જરૂરી શ્રેણીમાં આવે છે.

ઉદાહરણ તરીકે, cacheDataBlockPercent = 20 સેટ કરો અને જુઓ શું થાય છે:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

પરિણામ સ્પષ્ટ છે. નીચેના ગ્રાફમાં, તે સ્પષ્ટ થઈ જાય છે કે આવી પ્રવેગકતા શા માટે આવી છે - અમે ફક્ત કેશમાં ડેટા મૂકવાનું સીસીફીન કાર્ય કર્યા વિના ઘણા બધા GC સંસાધનો બચાવીએ છીએ અને તેને તરત જ મંગળના કૂતરાઓના ગટરમાં ફેંકી દઈએ છીએ:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

તે જ સમયે, CPU નો ઉપયોગ વધે છે, પરંતુ ઉત્પાદકતા કરતા ઘણો ઓછો છે:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

તે નોંધવું પણ યોગ્ય છે કે BlockCache માં સંગ્રહિત બ્લોક્સ અલગ છે. મોટાભાગના, લગભગ 95%, પોતે જ ડેટા છે. અને બાકીનો મેટાડેટા છે, જેમ કે બ્લૂમ ફિલ્ટર્સ અથવા LEAF_INDEX અને વગેરે. આ ડેટા પૂરતો નથી, પરંતુ તે ખૂબ જ ઉપયોગી છે, કારણ કે ડેટાને સીધો એક્સેસ કરતા પહેલા, HBase એ સમજવા માટે મેટા તરફ વળે છે કે શું અહીં આગળ શોધવું જરૂરી છે અને જો એમ હોય તો, રસનો બ્લોક બરાબર ક્યાં સ્થિત છે.

તેથી, કોડમાં આપણે ચેકની સ્થિતિ જોઈએ છીએ buf.getBlockType().isData() અને આ મેટા માટે આભાર, અમે તેને કોઈપણ સંજોગોમાં કેશમાં છોડીશું.

હવે ચાલો લોડ વધારીએ અને એક જ વારમાં ફીચરને થોડું કડક કરીએ. પ્રથમ ટેસ્ટમાં અમે કટઓફ ટકાવારી = 20 બનાવી અને બ્લોકકેશનો થોડો ઓછો ઉપયોગ કરવામાં આવ્યો. હવે ચાલો તેને 23% પર સેટ કરીએ અને કયા બિંદુએ સંતૃપ્તિ થાય છે તે જોવા માટે દર 100 મિનિટે 5 થ્રેડો ઉમેરીએ:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

અહીં આપણે જોઈએ છીએ કે મૂળ સંસ્કરણ લગભગ તરત જ પ્રતિ સેકન્ડ લગભગ 100 હજાર વિનંતીઓ પર ટોચમર્યાદાને હિટ કરે છે. જ્યારે પેચ 300 હજાર સુધીનું પ્રવેગક આપે છે. તે જ સમયે, તે સ્પષ્ટ છે કે વધુ પ્રવેગક હવે "ફ્રી" નથી; CPU ઉપયોગ પણ વધી રહ્યો છે.

જો કે, આ ખૂબ જ ભવ્ય ઉકેલ નથી, કારણ કે આપણે અગાઉથી જાણતા નથી કે કેટલા ટકા બ્લોક્સને કેશ કરવાની જરૂર છે, તે લોડ પ્રોફાઇલ પર આધારિત છે. તેથી, વાંચન કામગીરીની પ્રવૃત્તિના આધારે આ પરિમાણને આપમેળે સમાયોજિત કરવા માટે એક પદ્ધતિ લાગુ કરવામાં આવી હતી.

આને નિયંત્રિત કરવા માટે ત્રણ વિકલ્પો ઉમેરવામાં આવ્યા છે:

hbase.lru.cache.heavy.eviction.count.limit — અમે ઑપ્ટિમાઇઝેશનનો ઉપયોગ શરૂ કરીએ તે પહેલાં કેશમાંથી ડેટા બહાર કાઢવાની પ્રક્રિયા કેટલી વખત ચાલવી જોઈએ તે સેટ કરે છે (એટલે ​​કે બ્લોક્સ છોડવા). ડિફૉલ્ટ રૂપે તે MAX_INT = 2147483647 ની બરાબર છે અને વાસ્તવમાં તેનો અર્થ એ છે કે સુવિધા આ મૂલ્ય સાથે ક્યારેય કામ કરવાનું શરૂ કરશે નહીં. કારણ કે બહાર કાઢવાની પ્રક્રિયા દર 5 - 10 સેકન્ડે શરૂ થાય છે (તે લોડ પર આધાર રાખે છે) અને 2147483647 * 10 / 60 / 60 / 24 / 365 = 680 વર્ષ. જો કે, અમે આ પરિમાણને 0 પર સેટ કરી શકીએ છીએ અને સુવિધાને લોન્ચ કર્યા પછી તરત જ કાર્ય કરી શકીએ છીએ.

જો કે, આ પરિમાણમાં પેલોડ પણ છે. જો આપણો ભાર એવો હોય કે ટૂંકા ગાળાના વાંચન (દિવસ દરમિયાન કહો) અને લાંબા ગાળાના વાંચન (રાત્રે) સતત એકબીજા સાથે જોડાયેલા હોય, તો અમે ખાતરી કરી શકીએ છીએ કે જ્યારે લાંબી વાંચન કામગીરી ચાલુ હોય ત્યારે જ સુવિધા ચાલુ છે.

ઉદાહરણ તરીકે, અમે જાણીએ છીએ કે ટૂંકા ગાળાના વાંચન સામાન્ય રીતે લગભગ 1 મિનિટ ચાલે છે. બ્લોક્સ ફેંકવાનું શરૂ કરવાની કોઈ જરૂર નથી, કેશ પાસે જૂનું થવાનો સમય નથી અને પછી આપણે આ પરિમાણને સમાન સેટ કરી શકીએ છીએ, ઉદાહરણ તરીકે, 10. આ હકીકત તરફ દોરી જશે કે ઑપ્ટિમાઇઝેશન ત્યારે જ કામ કરવાનું શરૂ કરશે જ્યારે લાંબા- શબ્દ સક્રિય વાંચન શરૂ થયું છે, એટલે કે. 100 સેકન્ડમાં. આમ, જો અમારી પાસે ટૂંકા ગાળાનું વાંચન હોય, તો બધા બ્લોક્સ કેશમાં જશે અને ઉપલબ્ધ થશે (સિવાય કે જે પ્રમાણભૂત અલ્ગોરિધમ દ્વારા બહાર કાઢવામાં આવશે તે સિવાય). અને જ્યારે અમે લાંબા ગાળાના વાંચન કરીએ છીએ, ત્યારે સુવિધા ચાલુ થઈ જાય છે અને અમારી પાસે ઘણું વધારે પ્રદર્શન હશે.

hbase.lru.cache.heavy.eviction.mb.size.limit — અમે 10 સેકન્ડમાં કેશમાં કેટલા મેગાબાઇટ્સ મૂકવા માંગીએ છીએ તે સેટ કરે છે (અને, અલબત્ત, બહાર કાઢો). સુવિધા આ મૂલ્ય સુધી પહોંચવાનો અને તેને જાળવી રાખવાનો પ્રયાસ કરશે. મુદ્દો આ છે: જો આપણે કેશમાં ગીગાબાઇટ્સ નાખીએ, તો આપણે ગીગાબાઇટ્સ બહાર કાઢવી પડશે, અને આ, જેમ આપણે ઉપર જોયું, તે ખૂબ ખર્ચાળ છે. જો કે, તમારે તેને ખૂબ નાનું સેટ કરવાનો પ્રયાસ ન કરવો જોઈએ, કારણ કે આનાથી બ્લોક સ્કીપ મોડ અકાળે બહાર નીકળી જશે. શક્તિશાળી સર્વર્સ માટે (આશરે 20-40 ભૌતિક કોરો), લગભગ 300-400 MB સેટ કરવું શ્રેષ્ઠ છે. મધ્યમ વર્ગ માટે (~10 કોર) 200-300 MB. નબળા સિસ્ટમો માટે (2-5 કોર) 50-100 MB સામાન્ય હોઈ શકે છે (આના પર પરીક્ષણ કરાયું નથી).

ચાલો જોઈએ કે આ કેવી રીતે કાર્ય કરે છે: ચાલો કહીએ કે આપણે hbase.lru.cache.heavy.eviction.mb.size.limit = 500 સેટ કરીએ છીએ, ત્યાં અમુક પ્રકારનો લોડ (વાંચન) છે અને પછી દર ~10 સેકન્ડે આપણે ગણતરી કરીએ છીએ કે કેટલા બાઈટ હતા ફોર્મ્યુલાનો ઉપયોગ કરીને બહાર કાઢો:

ઓવરહેડ = ફ્રીડ બાઇટ્સ સમ (એમબી) * 100 / મર્યાદા (એમબી) - 100;

જો વાસ્તવમાં 2000 MB બહાર કાઢવામાં આવ્યા હોય, તો ઓવરહેડ બરાબર છે:

2000 * 100 / 500 - 100 = 300%

એલ્ગોરિધમ્સ થોડા દસ ટકા કરતાં વધુ જાળવવાનો પ્રયાસ કરે છે, તેથી સુવિધા કેશ્ડ બ્લોક્સની ટકાવારી ઘટાડશે, ત્યાં ઓટો-ટ્યુનિંગ મિકેનિઝમ અમલમાં મૂકશે.

જો કે, જો લોડ ઘટે છે, તો ચાલો કહીએ કે માત્ર 200 MB બહાર કાઢવામાં આવે છે અને ઓવરહેડ નકારાત્મક બની જાય છે (કહેવાતા ઓવરશૂટિંગ):

200 * 100 / 500 - 100 = -60%

તેનાથી વિપરીત, જ્યાં સુધી ઓવરહેડ સકારાત્મક ન બને ત્યાં સુધી સુવિધા કેશ્ડ બ્લોક્સની ટકાવારીમાં વધારો કરશે.

નીચે વાસ્તવિક ડેટા પર આ કેવી દેખાય છે તેનું ઉદાહરણ છે. 0% સુધી પહોંચવાનો પ્રયાસ કરવાની જરૂર નથી, તે અશક્ય છે. જ્યારે તે લગભગ 30 - 100% હોય ત્યારે તે ખૂબ જ સારું છે, આ ટૂંકા ગાળાના વધારા દરમિયાન ઑપ્ટિમાઇઝેશન મોડમાંથી અકાળે બહાર નીકળવાનું ટાળવામાં મદદ કરે છે.

hbase.lru.cache.heavy.eviction.overhead.coefficient - અમે પરિણામ કેટલી ઝડપથી મેળવવા માંગીએ છીએ તે સેટ કરે છે. જો આપણે ખાતરીપૂર્વક જાણીએ કે અમારા વાંચન મોટાભાગે લાંબા હોય છે અને રાહ જોવા માંગતા નથી, તો અમે આ ગુણોત્તર વધારી શકીએ છીએ અને ઝડપથી ઉચ્ચ પ્રદર્શન મેળવી શકીએ છીએ.

ઉદાહરણ તરીકે, અમે આ ગુણાંક = 0.01 સેટ કરીએ છીએ. આનો અર્થ એ છે કે ઓવરહેડ (ઉપર જુઓ) પરિણામી પરિણામ દ્વારા આ સંખ્યા દ્વારા ગુણાકાર કરવામાં આવશે અને કેશ્ડ બ્લોક્સની ટકાવારી ઘટાડવામાં આવશે. ચાલો ધારીએ કે ઓવરહેડ = 300% અને ગુણાંક = 0.01, તો કેશ્ડ બ્લોક્સની ટકાવારી 3% ઘટશે.

નકારાત્મક ઓવરહેડ (ઓવરશૂટિંગ) મૂલ્યો માટે સમાન "બેકપ્રેશર" તર્ક પણ લાગુ કરવામાં આવે છે. વાંચન અને હકાલપટ્ટીના વોલ્યુમમાં ટૂંકા ગાળાના વધઘટ હંમેશા શક્ય હોવાથી, આ પદ્ધતિ તમને ઑપ્ટિમાઇઝેશન મોડમાંથી અકાળે બહાર નીકળવાનું ટાળવા દે છે. બેકપ્રેશરમાં ઊંધી તર્ક હોય છે: ઓવરશૂટિંગ જેટલું મજબૂત છે, તેટલા વધુ બ્લોક્સ કેશ થાય છે.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

અમલીકરણ કોડ

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

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

          freedSumMb = 0;
          startTime = stopTime;
       }

ચાલો હવે એક વાસ્તવિક ઉદાહરણનો ઉપયોગ કરીને આ બધું જોઈએ. અમારી પાસે નીચેની ટેસ્ટ સ્ક્રિપ્ટ છે:

  1. ચાલો સ્કેન કરવાનું શરૂ કરીએ (25 થ્રેડો, બેચ = 100)
  2. 5 મિનિટ પછી, મલ્ટિ-ગેટ્સ ઉમેરો (25 થ્રેડો, બેચ = 100)
  3. 5 મિનિટ પછી, મલ્ટિ-ગેટ્સ બંધ કરો (ફક્ત ફરીથી સ્કેન બાકી છે)

અમે બે રન કરીએ છીએ, પ્રથમ hbase.lru.cache.heavy.eviction.count.limit = 10000 (જે વાસ્તવમાં સુવિધાને અક્ષમ કરે છે), અને પછી મર્યાદા = 0 સેટ કરો (તેને સક્ષમ કરે છે).

નીચેના લૉગ્સમાં આપણે જોઈએ છીએ કે કેવી રીતે સુવિધા ચાલુ છે અને ઓવરશૂટિંગને 14-71% પર ફરીથી સેટ કરે છે. સમય સમય પર લોડ ઘટે છે, જે બેકપ્રેશર ચાલુ કરે છે અને HBase ફરીથી વધુ બ્લોક્સ કેશ કરે છે.

લોગ RegionServer
ઇવિક્ટેડ (એમબી): 0, રેશિયો 0.0, ઓવરહેડ (%): -100, હેવી ઇવિક્શન કાઉન્ટર: 0, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 100
ઇવિક્ટેડ (એમબી): 0, રેશિયો 0.0, ઓવરહેડ (%): -100, હેવી ઇવિક્શન કાઉન્ટર: 0, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 100
ઇવિક્ટેડ (MB): 2170, રેશિયો 1.09, ઓવરહેડ (%): 985, હેવી ઇવિક્શન કાઉન્ટર: 1, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 91 < પ્રારંભ
ઇવિક્ટેડ (MB): 3763, રેશિયો 1.08, ઓવરહેડ (%): 1781, હેવી ઇવિક્શન કાઉન્ટર: 2, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 76
ઇવિક્ટેડ (MB): 3306, રેશિયો 1.07, ઓવરહેડ (%): 1553, હેવી ઇવિક્શન કાઉન્ટર: 3, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 61
ઇવિક્ટેડ (MB): 2508, રેશિયો 1.06, ઓવરહેડ (%): 1154, હેવી ઇવિક્શન કાઉન્ટર: 4, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 50
ઇવિક્ટેડ (MB): 1824, રેશિયો 1.04, ઓવરહેડ (%): 812, હેવી ઇવિક્શન કાઉન્ટર: 5, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 42
ઇવિક્ટેડ (MB): 1482, રેશિયો 1.03, ઓવરહેડ (%): 641, હેવી ઇવિક્શન કાઉન્ટર: 6, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 36
ઇવિક્ટેડ (MB): 1140, રેશિયો 1.01, ઓવરહેડ (%): 470, હેવી ઇવિક્શન કાઉન્ટર: 7, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 32
ઇવિક્ટેડ (MB): 913, રેશિયો 1.0, ઓવરહેડ (%): 356, હેવી ઇવિક્શન કાઉન્ટર: 8, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 29
ઇવિક્ટેડ (MB): 912, રેશિયો 0.89, ઓવરહેડ (%): 356, હેવી ઇવિક્શન કાઉન્ટર: 9, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 26
ઇવિક્ટેડ (MB): 684, રેશિયો 0.76, ઓવરહેડ (%): 242, હેવી ઇવિક્શન કાઉન્ટર: 10, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 24
ઇવિક્ટેડ (MB): 684, રેશિયો 0.61, ઓવરહેડ (%): 242, હેવી ઇવિક્શન કાઉન્ટર: 11, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 456, રેશિયો 0.51, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 12, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 21
ઇવિક્ટેડ (MB): 456, રેશિયો 0.42, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 13, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 20
ઇવિક્ટેડ (MB): 456, રેશિયો 0.33, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 14, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 15, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 342, રેશિયો 0.32, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 16, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 342, રેશિયો 0.31, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 17, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.3, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 18, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.29, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 19, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.27, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 20, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.25, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 21, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.24, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 22, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.22, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 23, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.21, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 24, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.2, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 25, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 228, રેશિયો 0.17, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 26, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 456, રેશિયો 0.17, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 27, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18 < ઉમેરાયેલ ગેટ્સ (પરંતુ ટેબલ સમાન)
ઇવિક્ટેડ (MB): 456, રેશિયો 0.15, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 28, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 342, રેશિયો 0.13, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 29, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 342, રેશિયો 0.11, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 30, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 342, રેશિયો 0.09, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 31, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.08, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 32, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.07, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 33, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.06, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 34, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.05, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 35, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.05, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 36, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 228, રેશિયો 0.04, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 37, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 109, રેશિયો 0.04, ઓવરહેડ (%): -46, હેવી ઇવિક્શન કાઉન્ટર: 37, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22 < બેક પ્રેશર
ઇવિક્ટેડ (MB): 798, રેશિયો 0.24, ઓવરહેડ (%): 299, હેવી ઇવિક્શન કાઉન્ટર: 38, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 20
ઇવિક્ટેડ (MB): 798, રેશિયો 0.29, ઓવરહેડ (%): 299, હેવી ઇવિક્શન કાઉન્ટર: 39, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 570, રેશિયો 0.27, ઓવરહેડ (%): 185, હેવી ઇવિક્શન કાઉન્ટર: 40, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 17
ઇવિક્ટેડ (MB): 456, રેશિયો 0.22, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 41, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 342, રેશિયો 0.16, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 42, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 342, રેશિયો 0.11, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 43, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 228, રેશિયો 0.09, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 44, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 228, રેશિયો 0.07, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 45, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 228, રેશિયો 0.05, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 46, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (MB): 222, રેશિયો 0.04, ઓવરહેડ (%): 11, હેવી ઇવિક્શન કાઉન્ટર: 47, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 16
ઇવિક્ટેડ (એમબી): 104, રેશિયો 0.03, ઓવરહેડ (%): -48, હેવી ઇવિક્શન કાઉન્ટર: 47, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 21 < ઇન્ટરપ્ટ મળે છે
ઇવિક્ટેડ (MB): 684, રેશિયો 0.2, ઓવરહેડ (%): 242, હેવી ઇવિક્શન કાઉન્ટર: 48, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 19
ઇવિક્ટેડ (MB): 570, રેશિયો 0.23, ઓવરહેડ (%): 185, હેવી ઇવિક્શન કાઉન્ટર: 49, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 342, રેશિયો 0.22, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 50, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 228, રેશિયો 0.21, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 51, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 228, રેશિયો 0.2, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 52, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 228, રેશિયો 0.18, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 53, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 228, રેશિયો 0.16, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 54, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 228, રેશિયો 0.14, ઓવરહેડ (%): 14, હેવી ઇવિક્શન કાઉન્ટર: 55, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 18
ઇવિક્ટેડ (MB): 112, રેશિયો 0.14, ઓવરહેડ (%): -44, હેવી ઇવિક્શન કાઉન્ટર: 55, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 23 < બેક પ્રેશર
ઇવિક્ટેડ (MB): 456, રેશિયો 0.26, ઓવરહેડ (%): 128, હેવી ઇવિક્શન કાઉન્ટર: 56, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.31, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 57, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 58, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 59, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 60, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 61, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 62, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 63, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.32, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 64, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 65, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 66, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.32, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 67, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 68, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.32, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 69, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.32, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 70, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 71, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 72, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 73, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 74, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 75, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (MB): 342, રેશિયો 0.33, ઓવરહેડ (%): 71, હેવી ઇવિક્શન કાઉન્ટર: 76, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 22
ઇવિક્ટેડ (એમબી): 21, રેશિયો 0.33, ઓવરહેડ (%): -90, હેવી ઇવિક્શન કાઉન્ટર: 76, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 32
ઇવિક્ટેડ (એમબી): 0, રેશિયો 0.0, ઓવરહેડ (%): -100, હેવી ઇવિક્શન કાઉન્ટર: 0, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 100
ઇવિક્ટેડ (એમબી): 0, રેશિયો 0.0, ઓવરહેડ (%): -100, હેવી ઇવિક્શન કાઉન્ટર: 0, વર્તમાન કેશીંગ ડેટાબ્લોક (%): 100

બે કેશ વિભાગો વચ્ચેના સંબંધના ગ્રાફના રૂપમાં સમાન પ્રક્રિયાને બતાવવા માટે સ્કેન જરૂરી હતા - સિંગલ (જ્યાં પહેલાં ક્યારેય વિનંતી કરવામાં આવી ન હોય તેવા બ્લોક્સ) અને મલ્ટી (ઓછામાં ઓછા એક વખત "વિનંતી કરાયેલ" ડેટા અહીં સંગ્રહિત છે):

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

અને અંતે, ગ્રાફના સ્વરૂપમાં પરિમાણોનું સંચાલન શું દેખાય છે. સરખામણી માટે, શરૂઆતમાં કેશ સંપૂર્ણપણે બંધ કરવામાં આવ્યું હતું, પછી HBase ને કેશીંગ સાથે લોન્ચ કરવામાં આવ્યું હતું અને ઑપ્ટિમાઇઝેશન કાર્ય શરૂ કરવામાં 5 મિનિટ (30 ઇવિક્શન સાઇકલ) દ્વારા વિલંબ થયો હતો.

પુલ વિનંતીમાં સંપૂર્ણ કોડ મળી શકે છે HBASE 23887 ગીથબ પર.

જો કે, આ શરતો હેઠળ આ હાર્ડવેર પર પ્રતિ સેકન્ડ 300 હજાર વાંચન પ્રાપ્ત કરી શકાય તેવું નથી. હકીકત એ છે કે જ્યારે તમારે HDFS મારફત ડેટા એક્સેસ કરવાની જરૂર હોય, ત્યારે ShortCircuitCache (ત્યારબાદ SSC તરીકે ઓળખવામાં આવે છે) મિકેનિઝમનો ઉપયોગ કરવામાં આવે છે, જે તમને નેટવર્કની ક્રિયાપ્રતિક્રિયાઓને ટાળીને સીધા ડેટાને ઍક્સેસ કરવાની મંજૂરી આપે છે.

પ્રોફાઇલિંગ બતાવે છે કે જો કે આ મિકેનિઝમ મોટો ફાયદો આપે છે, તે પણ અમુક સમયે અડચણ બની જાય છે, કારણ કે લગભગ તમામ ભારે કામગીરી લોકની અંદર થાય છે, જે મોટાભાગે અવરોધ તરફ દોરી જાય છે.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

આ સમજ્યા પછી, અમને સમજાયું કે સ્વતંત્ર SSC ની શ્રેણી બનાવીને સમસ્યાને દૂર કરી શકાય છે:

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

અને પછી તેમની સાથે કામ કરો, આંતરછેદોને બાદ કરતાં છેલ્લા ઑફસેટ અંક પર પણ:

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

હવે તમે પરીક્ષણ શરૂ કરી શકો છો. આ કરવા માટે, અમે એક સરળ મલ્ટી-થ્રેડેડ એપ્લિકેશન સાથે HDFS માંથી ફાઇલો વાંચીશું. પરિમાણો સેટ કરો:

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

અને ફક્ત ફાઇલો વાંચો:

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

આ કોડ અલગ થ્રેડોમાં એક્ઝિક્યુટ કરવામાં આવે છે અને અમે એકસાથે વાંચેલી ફાઇલોની સંખ્યા (10 થી 200 સુધી - આડી અક્ષ સુધી) અને કેશની સંખ્યા (1 થી 10 - ગ્રાફિક્સ સુધી) વધારીશું. વર્ટિકલ અક્ષ એ પ્રવેગક દર્શાવે છે જે માત્ર એક જ કેશ હોય ત્યારે કેસની તુલનામાં SSC માં વધારો થવાથી પરિણમે છે.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

ગ્રાફ કેવી રીતે વાંચવો: એક કેશ સાથે 100 KB બ્લોક્સમાં 64 હજાર વાંચવા માટેનો અમલ સમય 78 સેકન્ડની જરૂર છે. જ્યારે 5 કેશ સાથે તે 16 સેકન્ડ લે છે. તે. ત્યાં ~5 ગણો પ્રવેગ છે. ગ્રાફ પરથી જોઈ શકાય છે તેમ, ઓછી સંખ્યામાં સમાંતર વાંચન માટે અસર ખૂબ જ ધ્યાનપાત્ર નથી; જ્યારે 50 થી વધુ થ્રેડ રીડ હોય ત્યારે તે નોંધપાત્ર ભૂમિકા ભજવવાનું શરૂ કરે છે. તે પણ નોંધનીય છે કે 6 થી SSC ની સંખ્યામાં વધારો અને ઉપર નોંધપાત્ર રીતે નાનો પ્રભાવ વધારો આપે છે.

નોંધ 1: કારણ કે પરીક્ષણ પરિણામો તદ્દન અસ્થિર છે (નીચે જુઓ), 3 રન કરવામાં આવ્યા હતા અને પરિણામી મૂલ્યોની સરેરાશ કરવામાં આવી હતી.

નોંધ 2: રેન્ડમ એક્સેસને રૂપરેખાંકિત કરવાથી પરફોર્મન્સ ગેઇન સમાન છે, જો કે એક્સેસ પોતે જ થોડી ધીમી છે.

જો કે, તે સ્પષ્ટ કરવું જરૂરી છે કે, HBase સાથેના કેસથી વિપરીત, આ પ્રવેગક હંમેશા મફત નથી. અહીં આપણે તાળાઓ પર લટકાવવાને બદલે વધુ કામ કરવાની CPU ની ક્ષમતાને "અનલૉક" કરીએ છીએ.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

અહીં તમે અવલોકન કરી શકો છો કે, સામાન્ય રીતે, કેશની સંખ્યામાં વધારો CPU વપરાશમાં આશરે પ્રમાણસર વધારો આપે છે. જો કે, ત્યાં થોડી વધુ વિજેતા સંયોજનો છે.

ઉદાહરણ તરીકે, ચાલો SSC = 3 સેટિંગ પર નજીકથી નજર કરીએ. શ્રેણી પર પ્રદર્શનમાં વધારો લગભગ 3.3 ગણો છે. નીચે ત્રણેય અલગ-અલગ રનના પરિણામો છે.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

જ્યારે CPU વપરાશ લગભગ 2.8 ગણો વધે છે. તફાવત બહુ મોટો નથી, પરંતુ નાની ગ્રેટા પહેલેથી જ ખુશ છે અને તેની પાસે શાળામાં જવા અને પાઠ લેવાનો સમય હોઈ શકે છે.

આમ, HDFS (ઉદાહરણ તરીકે સ્પાર્ક, વગેરે) ની બલ્ક એક્સેસનો ઉપયોગ કરતા કોઈપણ ટૂલ માટે આની સકારાત્મક અસર પડશે, જો કે એપ્લિકેશન કોડ હળવો હોય (એટલે ​​​​કે પ્લગ HDFS ક્લાયંટ બાજુ પર હોય) અને મફત CPU પાવર હોય. . ચકાસવા માટે, ચાલો ચકાસીએ કે HBase થી વાંચવા માટે BlockCache ઑપ્ટિમાઇઝેશન અને SSC ટ્યુનિંગના સંયુક્ત ઉપયોગની શું અસર થશે.

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

તે જોઈ શકાય છે કે આવી પરિસ્થિતિઓમાં અસર શુદ્ધ પરીક્ષણો જેટલી મહાન નથી (કોઈપણ પ્રક્રિયા વિના વાંચન), પરંતુ અહીં વધારાના 80K સ્ક્વિઝ કરવાનું તદ્દન શક્ય છે. એકસાથે, બંને ઑપ્ટિમાઇઝેશન 4x સુધીની ઝડપ પૂરી પાડે છે.

આ ઑપ્ટિમાઇઝેશન માટે PR પણ બનાવવામાં આવ્યું હતું [HDFS-15202], જે મર્જ કરવામાં આવ્યું છે અને આ કાર્યક્ષમતા ભવિષ્યના પ્રકાશનોમાં ઉપલબ્ધ થશે.

અને છેલ્લે, સમાન વિશાળ-કૉલમ ડેટાબેઝ, Cassandra અને HBase ના વાંચન પ્રદર્શનની સરખામણી કરવી રસપ્રદ હતી.

આ કરવા માટે, અમે બે યજમાનો (કુલ 800 થ્રેડો) પાસેથી પ્રમાણભૂત YCSB લોડ ટેસ્ટિંગ યુટિલિટીના દાખલા લોન્ચ કર્યા છે. સર્વર બાજુ પર - 4 હોસ્ટ્સ પર RegionServer અને Cassandra ના 4 ઉદાહરણો (તેના પ્રભાવને ટાળવા માટે જ્યાં ક્લાયંટ ચાલી રહ્યા છે તે નહીં). રીડિંગ્સ કદના કોષ્ટકોમાંથી આવ્યા છે:

HBase - HDFS પર 300 GB (100 GB શુદ્ધ ડેટા)

કસાન્ડ્રા - 250 જીબી (પ્રતિકૃતિ પરિબળ = 3)

તે. વોલ્યુમ લગભગ સમાન હતું (HBase માં થોડું વધારે).

HBase પરિમાણો:

dfs.client.short.circuit.num = 5 (HDFS ક્લાયંટ ઑપ્ટિમાઇઝેશન)

hbase.lru.cache.heavy.eviction.count.limit = 30 - આનો અર્થ એ છે કે પેચ 30 નિકાલ પછી કામ કરવાનું શરૂ કરશે (~5 મિનિટ)

hbase.lru.cache.heavy.eviction.mb.size.limit = 300 - કેશીંગ અને ઇવિક્શનનું લક્ષ્ય વોલ્યુમ

YCSB લૉગ્સ એક્સેલ ગ્રાફમાં વિશ્લેષિત અને સંકલિત કરવામાં આવ્યા હતા:

HBase થી 3 ગણી અને HDFS થી 5 ગણી સુધી વાંચવાની ઝડપ કેવી રીતે વધારવી

જેમ તમે જોઈ શકો છો, આ ઑપ્ટિમાઇઝેશન આ શરતો હેઠળ આ ડેટાબેસેસના પ્રદર્શનની તુલના કરવાનું શક્ય બનાવે છે અને પ્રતિ સેકન્ડ 450 હજાર વાંચન પ્રાપ્ત કરે છે.

અમે આશા રાખીએ છીએ કે ઉત્પાદકતા માટેના ઉત્તેજક સંઘર્ષ દરમિયાન આ માહિતી કોઈને ઉપયોગી થઈ શકે.

સોર્સ: www.habr.com

એક ટિપ્પણી ઉમેરો