總結(jié)下工作中遇到的GC問題篡石。
一恕洲、JVM參數(shù)設(shè)置不當(dāng)
機(jī)器4G,部分JVM參數(shù)設(shè)置
-Xmx3296m -Xms3296m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxGCPauseMillis=200 -XX:+UseG1GC
-XX:-OmitStackTraceInFastThrow -XX:MinHeapFreeRatio=30 -XX:MaxHeapFreeRatio=50
現(xiàn)象:young GC比較頻繁盐碱,并且不穩(wěn)定楼誓,每1玉锌、2個小時會出現(xiàn)YGC次數(shù)激增,偶爾伴隨Full GC疟羹,此時CPU狀態(tài)也上升到100%主守。
查看日志:
分析原因:G1 GC動態(tài)調(diào)整新生代大匈骶蟆(默認(rèn)5%-60%),從日志看出調(diào)整后的Eden區(qū)太小参淫,導(dǎo)致很容易發(fā)生young gc救湖。
解決方案:
調(diào)整JVM參數(shù),將新生代下限從5%調(diào)整到35%:
-XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=35 -XX:G1MaxNewSizePercent=60
補(bǔ)充:Google時涎才,看到說因為G1需要Mixed GC鞋既,Mixed GC會掃描Eden,Survivor耍铜,和1/8(默認(rèn))Old邑闺。因為比Young GC多掃描Old區(qū),所以為了盡力實現(xiàn)最大停頓時間棕兼,在Mixed GC前的Young GC急劇縮小了Eden Heap的大小检吆,所以調(diào)大最大停頓時間也能緩解此問題。
結(jié)果:YGC次數(shù)更平穩(wěn)程储,F(xiàn)GC未出現(xiàn)
二蹭沛、代碼不合理
現(xiàn)象:每3小時出現(xiàn)一次YGC時間超過超過300ms,此時CPU和網(wǎng)絡(luò)狀態(tài)正常章鲤,只有內(nèi)存增加摊灭。
當(dāng)時排障的日志沒截圖保存下來,簡單說一下主要耗時就是Object Copy占了大量時間败徊,如圖紅色框部分
日志中各參數(shù)含義可以參考:
分析:通過代碼發(fā)現(xiàn)每3個小時會全量拉一批某表的信息做本地緩存帚呼。Object Copy占了大量時間,說明需要Copy的對象很多皱蹦。因為是緩存對象煤杀,所以不能回收。
解決方案:使用增量刷新的方式沪哺。偽代碼:
int total = getTotalCount();
int pageSize = 500;
int(int i = 0 , i < total, i += pageSize){
List list = exec("select * from my_table limit ?,?", i ,pageSize)
CACHE.putAll(list);
}
采用這種方法需要注意的點:
1.可能導(dǎo)致刷新的數(shù)據(jù)不全沈自,在刷新緩存時如果有新數(shù)據(jù)插入,則可能導(dǎo)致部分的緩存沒有刷新辜妓。該問題的優(yōu)化方式之一是:更新完緩存后看緩存的size是否等于表中數(shù)據(jù)的條數(shù)枯途,如果不等于,說明刷新緩存過程中出現(xiàn)了變動籍滴,可以重新更新緩存(CAS思想)酪夷。
2.這種改進(jìn)方法降低了吞吐量,一般來說這種定時任務(wù)都是以吞吐量為優(yōu)先孽惰,改進(jìn)這個問題是因為該問題影響了我系統(tǒng)的其他實時性功能晚岭,所以需不需要改進(jìn)還是根據(jù)自己系統(tǒng)的需求。