日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java的前生今世_HBaseGC的前生今世-身世篇

發(fā)布時(shí)間:2023/12/1 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的前生今世_HBaseGC的前生今世-身世篇 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

網(wǎng)易視頻云是網(wǎng)易傾力打造的一款基于云計(jì)算的分布式多媒體處理集群和專業(yè)音視頻技術(shù),提供穩(wěn)定流暢、低時(shí)延、高并發(fā)的視頻直播、錄制、存儲(chǔ)、轉(zhuǎn)碼及點(diǎn)播等音視頻的PAAS服務(wù),在線教育、遠(yuǎn)程醫(yī)療、娛樂秀

網(wǎng)易視頻云是網(wǎng)易傾力打造的一款基于云計(jì)算的分布式多媒體處理集群和專業(yè)音視頻技術(shù),提供穩(wěn)定流暢、低時(shí)延、高并發(fā)的視頻直播、錄制、存儲(chǔ)、轉(zhuǎn)碼及點(diǎn)播等音視頻的PAAS服務(wù),在線教育、遠(yuǎn)程醫(yī)療、娛樂秀場(chǎng)、在線金融等各行業(yè)及企業(yè)用戶只需經(jīng)過(guò)簡(jiǎn)單的開發(fā)即可打造在線音視頻平臺(tái)?,F(xiàn)在,網(wǎng)易視頻云的技術(shù)專家給大家分享一則技術(shù)文:HBase GC的前生今世 - 身世篇。

在之前的HBase BlockCache系列文章中已經(jīng)簡(jiǎn)單提到:使用LRUBlockCache緩存機(jī)制會(huì)因?yàn)镃MS GC策略導(dǎo)致內(nèi)存碎片過(guò)多,從而可能引發(fā)臭名昭著的Full GC,觸發(fā)可怕的’stop-the-world’暫停,嚴(yán)重影響上層業(yè)務(wù);而Bucket Cache緩存機(jī)制因?yàn)樵诔跏蓟臅r(shí)候就申請(qǐng)了一片固定大小的內(nèi)存作為緩存,緩存淘汰不再由 JVM管理,數(shù)據(jù)Block的緩存操作只是對(duì)這篇空間的訪問和覆蓋,因而大大減少了內(nèi)存碎片的出現(xiàn),降低了Full GC發(fā)生的頻率。那CMS

GC策略如何導(dǎo)致內(nèi)存碎片過(guò)多?內(nèi)存碎片過(guò)多如何觸發(fā)Full GC?HBase在演進(jìn)的道路上又如何不斷優(yōu)化CMS GC?接下來(lái)這個(gè)系列《HBase GC的前生今生》將會(huì)為你一一揭開謎底,這個(gè)系列一共兩篇文章,本篇文章-’身世篇’將會(huì)帶你全面了解HBase的GC機(jī)制,后面一篇-’演進(jìn)篇’將會(huì)給你道出HBase在發(fā)展的道路上如何不斷對(duì)Full GC進(jìn)行優(yōu)化。

Java GC概述

整個(gè)HBase是構(gòu)建在JVM虛擬機(jī)上的,因此了解HBase的內(nèi)存管理機(jī)制以及不同緩存機(jī)制對(duì)GC的影響,就必須對(duì)Java GC有一個(gè)全面的了解。至于深入地理解Java GC 的工作原理,不在本文的討論范圍之內(nèi);當(dāng)然,如果已經(jīng)對(duì)Java GC比較熟悉,也可以跳過(guò)此節(jié)。

Java GC建立在這樣一個(gè)假設(shè)基礎(chǔ)上的:大多數(shù)內(nèi)存對(duì)象要么生存周期比較短,很快就會(huì)沒人引用,比如處理RPC請(qǐng)求的buffer可能只會(huì)生存幾微秒;要么生存周期比較長(zhǎng),比如Block Cache中的熱點(diǎn)Block,可能就會(huì)生存幾分鐘,甚至更長(zhǎng)時(shí)間?;谶@樣的事實(shí),JVM將整個(gè)堆內(nèi)存分為兩個(gè)部分:新生代(young generation)和老生代(tenured generation),除此之外,JVM還有一個(gè)非堆內(nèi)存區(qū)-Perm區(qū),主要存放class信息以及其他meta元信息,內(nèi)存結(jié)構(gòu)如下圖所示:

其中Young區(qū)又分為Eden區(qū)和兩個(gè)Survivor 區(qū):S0和S1。一個(gè)內(nèi)存對(duì)象在創(chuàng)建之后,首先會(huì)為其在新生代申請(qǐng)一塊內(nèi)存空間,如果這個(gè)對(duì)象在新生代存活了很長(zhǎng)時(shí)間,會(huì)將其遷移到老生代。 在大多數(shù)對(duì)延遲敏感的業(yè)務(wù)場(chǎng)景下(比如HBase),建議使用如下JVM參數(shù),-XX:+UseParNewGC和XX:+UseConcMarkSweepGC,其中前者表示對(duì)新生代執(zhí)行并行的垃圾回收機(jī)制,而后者表示對(duì)老生代執(zhí)行并行標(biāo)記-清除垃圾回收機(jī)制??梢?#xff0c;JVM允許針對(duì)不同內(nèi)存區(qū)執(zhí)行不同的GC策略。

新生代GC策略 – Parallel New Collector

根據(jù)上文所述,對(duì)象初始化之后會(huì)被放入Young區(qū),更具體的話應(yīng)該是Eden區(qū),當(dāng)Eden區(qū)滿了之后,會(huì)進(jìn)行一次GC。GC算法會(huì)檢查所有對(duì)象的引用情況,如果某個(gè)對(duì)象還有被引用,表示該對(duì)象存活。檢查完成之后,會(huì)將這些存活的對(duì)象移到S0區(qū),并且回收整個(gè)Eden區(qū)空間,稱為一次Minor GC;接著新對(duì)象進(jìn)來(lái),又會(huì)放入Eden區(qū),滿了之后會(huì)檢查S0和Eden區(qū)存活的對(duì)象,將所有存活的對(duì)象移到S1區(qū),再回收整個(gè)S0和Eden區(qū)空間;很容易理解,S0和S1兩個(gè)區(qū)總會(huì)有一個(gè)區(qū)是預(yù)留給下次存放存活對(duì)象用的。

整個(gè)過(guò)程可以使用如下圖示:

這種算法稱為復(fù)制算法,對(duì)于這種算法,有兩點(diǎn)需要關(guān)注:

1. 算法會(huì)執(zhí)行’stop-the-world’暫停,但時(shí)間非常短。因?yàn)閅oung區(qū)通常會(huì)設(shè)置的比較小(一般不建議不超過(guò)512M),而且JVM會(huì)啟動(dòng)大量線程并發(fā)執(zhí)行,一次Minor GC一般都會(huì)在幾毫秒內(nèi)完成

2. 不會(huì)產(chǎn)生碎片,每次GC之后都會(huì)將存活的對(duì)象放入連續(xù)的空間(S0或S1)

內(nèi)存中所有對(duì)象都會(huì)維護(hù)一個(gè)計(jì)數(shù)器,每次Minor GC移動(dòng)一個(gè)對(duì)象之后,都會(huì)為這個(gè)對(duì)象的計(jì)數(shù)器加一。當(dāng)計(jì)數(shù)器增加到一定閾值之后,算法就會(huì)認(rèn)為該對(duì)象生命周期很長(zhǎng),會(huì)將其移入老生代。該閾值可以通過(guò)JVM參數(shù)XX:MaxTenuringThreshold指定。

老生代GC策略 – Concurrent Mark-Sweep

每次執(zhí)行Minor GC之后,都會(huì)有部分生命周期較長(zhǎng)的對(duì)象被移入老生代,一段時(shí)間之后,老生代空間也會(huì)被占滿。此時(shí)就需要針對(duì)老生代空間執(zhí)行GC操作,此處我們介紹Concurrent Mark-Sweep(CMS)算法。CMS算法整個(gè)流程分為6個(gè)階段,其中部分階段會(huì)執(zhí)行 ‘stop-the-world’ 暫停,部分階段會(huì)和應(yīng)用線程一起并發(fā)執(zhí)行:

1. initial-mark:這個(gè)階段虛擬機(jī)會(huì)暫停所有正在執(zhí)行的任務(wù)。這一過(guò)程虛擬機(jī)會(huì)標(biāo)記所有 ‘根對(duì)象’,所謂‘根對(duì)象’,一般是指一個(gè)運(yùn)行線程直接引用到的對(duì)象。雖然會(huì)暫停整個(gè)JVM,但因?yàn)椤鶎?duì)象’相對(duì)較少,這個(gè)過(guò)程通常很快。

2. concurrent mark:垃圾回收器會(huì)從‘根節(jié)點(diǎn)’開始,將所有引用到的對(duì)象都打上標(biāo)記。這個(gè)階段應(yīng)用程序的線程和標(biāo)記線程并發(fā)執(zhí)行,因此用戶并不會(huì)感到停頓。

3. concurrent precleaning:并發(fā)預(yù)清理階段仍然是并發(fā)的。在這個(gè)階段,虛擬機(jī)查找在執(zhí)行mark階段新進(jìn)入老年代的對(duì)象(可能會(huì)有一些對(duì)象從新生代晉升到老年代, 或者有一些對(duì)象被分配到老年代)。

4. remark:在階段3的基礎(chǔ)上對(duì)查找到的對(duì)象進(jìn)行重新標(biāo)記,這一階段會(huì)暫停整個(gè)JVM,但是因?yàn)殡A段3已經(jīng)欲檢查出了所有新進(jìn)入的對(duì)象,因此這個(gè)過(guò)程也會(huì)很快。

5. concurrent sweep:上述3階段完成了引用對(duì)象的標(biāo)記,此階段會(huì)將所有沒有標(biāo)記的對(duì)象作為垃圾回收掉。這個(gè)階段應(yīng)用程序的線程和標(biāo)記線程并發(fā)執(zhí)行。

6. concurrent reset:重置CMS收集器的數(shù)據(jù)結(jié)構(gòu),等待下一次垃圾回收。

相應(yīng)的,對(duì)于CMS算法,也需要關(guān)注兩點(diǎn):

1. ‘stop-the-world’暫停時(shí)間也很短暫,耗時(shí)較長(zhǎng)的標(biāo)記和清理都是并發(fā)執(zhí)行的。

2. CMS算法在標(biāo)記清理之后并沒有重新壓縮分配存活對(duì)象,因此整個(gè)老生代會(huì)產(chǎn)生很多的內(nèi)存碎片。

CMS Failure Mode

上文提到在正常的情況下CMS整個(gè)流程的暫停時(shí)間都是很短的,一般也就在10ms~100ms左右。然而這與線上的情況并不相符,線上集群在讀寫壓力很大的情況下,經(jīng)常會(huì)出現(xiàn)長(zhǎng)時(shí)間的卡頓,有些卡頓甚至長(zhǎng)達(dá)幾分鐘,導(dǎo)致很嚴(yán)重的讀寫阻塞,甚至?xí)斐蒖egion Server和Zookeeper之間Session超時(shí),使得Region Server異常離線。實(shí)際上,CMS并不是很完美,它會(huì)在兩種場(chǎng)景下產(chǎn)生嚴(yán)重的Full GC,接下來(lái)分別進(jìn)行介紹。

Concurrent Failure

這種場(chǎng)景其實(shí)比較簡(jiǎn)單,假如現(xiàn)在系統(tǒng)正在執(zhí)行CMS回收老生代空間,在回收的過(guò)程中新生代來(lái)了一批對(duì)象進(jìn)來(lái),不巧的是,老生代已經(jīng)沒有空間再容納這些對(duì)象了。這種場(chǎng)景下,CMS回收器會(huì)停止繼續(xù)工作,系統(tǒng)進(jìn)入 ’stop-the-world’ 模式,并且回收算法會(huì)退化為單線程復(fù)制算法,重新分配整個(gè)堆內(nèi)存的存活對(duì)象到S0中,釋放所有其他空間。很顯然,整個(gè)過(guò)程會(huì)非?!L(zhǎng)’。但是這種問題也很容易解決,只需要讓CMS回收器更早一點(diǎn)回收就可以避免。JVM提供了參數(shù)-XX:CMSInitiatingOccupancyFraction=N來(lái)設(shè)置CMS回收的時(shí)機(jī),其中N表示當(dāng)前老生代已使用內(nèi)存占新生代總內(nèi)存的比例,該值默認(rèn)為68,可以將該值修改的更小使得回收更早進(jìn)行。

Promotion Failure

假設(shè)此時(shí)設(shè)置XX:CMSInitiatingOccupancyFraction=60,但是在已使用內(nèi)存還沒有達(dá)到總內(nèi)存60%的時(shí)候,已經(jīng)沒有空間容納從新生代遷移的對(duì)象了。oh,my god!怎么會(huì)這樣?罪魁禍?zhǔn)拙褪莾?nèi)存碎片,上文中提到CMS算法會(huì)產(chǎn)生大量碎片,當(dāng)碎片容量積累到一定大小之后就會(huì)造成上面的場(chǎng)景。這種場(chǎng)景下,CMS回收器一樣會(huì)停止工作,進(jìn)入漫長(zhǎng)的 ’stop-the-world’ 模式。JVM也提供了參數(shù) -XX: UseCMSCompactAtFullCollection來(lái)減少碎片的產(chǎn)生,這個(gè)參數(shù)表示會(huì)在每次CMS回收垃圾之后執(zhí)行一次碎片整理,很顯然,這個(gè)參數(shù)會(huì)對(duì)性能有比較大的影響,對(duì)HBase這種對(duì)延遲敏感的業(yè)務(wù)來(lái)說(shuō)并不是一個(gè)完美解決方案。

HBase內(nèi)存碎片統(tǒng)計(jì)實(shí)驗(yàn)

在實(shí)際線上環(huán)境中,很少出現(xiàn)Concurrent Failure模式的Full GC,大多數(shù)Full GC場(chǎng)景都是Promotion Failure。我們線上集群也會(huì)每隔半個(gè)月左右就會(huì)因?yàn)镻romotion Failure觸發(fā)一次Full GC。為了更好地理解CMS策略下內(nèi)存碎片是如何觸發(fā)Promotion Failure,接下來(lái)我們做一個(gè)簡(jiǎn)單的實(shí)驗(yàn):JVM提供了參數(shù) -XX:PrintFLSStatistics=1來(lái)打印每次GC前后內(nèi)存碎片的統(tǒng)計(jì)信息,統(tǒng)計(jì)信息主要包括3個(gè)維度:Free

Space、Max Chunk Size和Num Chunks,其中Free Space表示老生代當(dāng)前空閑的總內(nèi)存容量,Max Chunk Size表示老生代中最大的內(nèi)存碎片所占的內(nèi)存容量大小,Num Chunks表示老生代中總的內(nèi)存碎片數(shù)。我們?cè)跍y(cè)試環(huán)境集群(共4臺(tái)Region Server)將這個(gè)參數(shù)設(shè)置為1,然后使用一個(gè)客戶端YCSB執(zhí)行Read-And-Write操作,分別統(tǒng)計(jì)日志中Free Space和Max Chunk Size兩個(gè)指標(biāo)隨時(shí)間的變化情況。

測(cè)試結(jié)果如下圖所示,其中第一張圖表示Total Free Space隨時(shí)間的變化曲線圖,第二張圖表示Max Chunk Size隨時(shí)間變化曲線圖。其中橫坐標(biāo)表示時(shí)間,縱坐標(biāo)表示相應(yīng)內(nèi)存大小。

根據(jù)第一張曲線圖可知,老生代總的空閑內(nèi)存容量維持在300M~400M之間,當(dāng)內(nèi)存容量到達(dá)300M左右時(shí)就會(huì)進(jìn)行一次GC,GC后內(nèi)存容量就會(huì)又回到400M左右。而第二張曲線圖會(huì)更加形象地說(shuō)明內(nèi)存碎片導(dǎo)致的Promotion Failure,剛開始隨著數(shù)據(jù)不斷寫入,Max Chunk Size會(huì)不斷變小,之后很長(zhǎng)一段時(shí)間基本維持在30M左右。在橫坐標(biāo)為1093那點(diǎn),人為地將寫入的單條數(shù)據(jù)大小由500Byte變?yōu)?M大小,此后Max Chunk Size會(huì)再次減小,當(dāng)減小到一定程度之后曲線會(huì)忽然升高到350M左右,經(jīng)過(guò)日志確認(rèn),此時(shí)JVM發(fā)生了Promotion

Failure模式的Full GC,持續(xù)時(shí)間約4.91s。此后一段時(shí)間Full GC還在持續(xù)發(fā)生。

經(jīng)過(guò)上述分析,可以知道:CMS GC會(huì)不斷產(chǎn)生內(nèi)存碎片,當(dāng)碎片小到一定程度之后就會(huì)基本維持不變,如果此時(shí)業(yè)務(wù)寫入一些單條數(shù)據(jù)量很大的KeyValue,就有可能觸發(fā)Promotion Failure模式Full GC。

總結(jié)

本文首先介紹了兩種常見的Java GC策略,再接著介紹了CMS策略可能引起兩種模式的Full GC,最后通過(guò)一個(gè)小實(shí)驗(yàn)說(shuō)明了CMS GC確實(shí)產(chǎn)生了內(nèi)存碎片,而且會(huì)導(dǎo)致長(zhǎng)時(shí)間的Full GC發(fā)生。接下來(lái)《演進(jìn)篇》會(huì)詳細(xì)介紹從一開始HBase是如何針對(duì)CMS進(jìn)行優(yōu)化處理的,敬請(qǐng)期待!

Categories:更多技術(shù)交流,請(qǐng)關(guān)注我們進(jìn)行交流與咨詢哦!

本條技術(shù)文章來(lái)源于互聯(lián)網(wǎng),如果無(wú)意侵犯您的權(quán)益請(qǐng)點(diǎn)擊此處反饋版權(quán)投訴

本文系統(tǒng)來(lái)源:php中文網(wǎng)

總結(jié)

以上是生活随笔為你收集整理的java的前生今世_HBaseGC的前生今世-身世篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。