mycat自動重啓解決辦法

mycat自動重啓解決辦法
前言
mycat是一個非常著名的分庫分表中間件,但是很多使用過這個中間件的人都會遇到一個共通的問題,那就是mycat的進程總是會重啓,同時重啓的時候應用的代碼裏面也會報出 Java.lang.NullPoint_er_Exception , 今天就來分析一下這個問題,以及解決辦法!

原理
這個mycat的重啓問題可能一部分人遇到了,一部分人沒有遇到過,這是爲什麼呢?

實際上這段mycat的bug代碼是出現在了跨庫結果集合並後,釋放堆外內存的代碼上面
有一部分有經驗的人知道分庫分表中間件是不太適用於跨庫查詢的,這些有經驗的人會讓業務代碼去一個一個庫查出數據庫後,讓業務代碼自己去做數據合併,排序的邏輯,如果是這樣的話就完美避開了這個問題。

比如我用mycat的註解

/#mycat: datanode=dn1/select * from ljj_table

/#mycat: datanode=dn2/select * from ljj_table

這樣就強行指定了datanode的節點,就算我sql裏面沒有分庫字段也可以去這個庫裏面查出數據。然後在業務裏面把select出來的結果進行合併

但是對於很多中小型的公司來說,因爲經驗不足,以及代碼的快速迭代,是允許mycat跨庫查詢的,這就導致了mycat內部需要做排序,這樣做的話就有機率觸發堆外內存重複釋放的bug導致重啓。

比如我直接執行

select * from ljj_table
這樣的sql,mycat內部就會進行匯聚以及排序,就會導致空指針。

代碼REVIEW以及修改方法
這個問題的代碼主要問題就是出在了 MultiNodeQueryHandler

這個類上面,在這個類裏面,有幾個釋放資源的類需要做出修改。

在方法 outputMergeResult(這個類裏面有2個outputMergeResult,都要改!)

裏面,我們需要調整釋解鎖與釋放堆外內存的順尋

原先是

lock.unlock();

dataMergeSvr.clear();
現在我們需要改成

dataMergeSvr.clear();

lock.unlock();
以及在這個類的clearResources方法裏面,我們需要加上鎖

原先是

if(dataMergeSvr!=null){

    dataMergeSvr.clear();

}
現在改成

lock.lock();

try{

if(dataMergeSvr!=null){

    dataMergeSvr.clear();

}

}finally{

lock.unlock();

}
這樣改完後,我們就保證了dataMergeSvr.clear()這個方法的原子性。

還有在AbstractConnection這個類上面的cleanup方法上面加上sync的鎖,這樣mycat的重啓問題就徹底修復了。

如果不修改源碼重新打包?有什麼簡單的方法可以直接改掉這個類嗎?(針對dba和運維)
答案是可以的!我知道很多公司維護mycat的都是dba和運維,這裏可以利用mycat自帶的wrapper功能(加載外部jar包)來進行直接修復

我把我改完的這2個類的jar(僅針對mycat1.6版本)已經上傳到了網盤

鏈接:https://pan.baidu.com/s/1coay5H-QE7ED26UWuKsL5g
提取碼:ygad

把我的這個jar包mycatExtend.jar放到mycat的lib目錄下

比如Mycat-server-1.6mycatlib下面

然後在conf文件裏面的wrapper.conf這個文件裏面設置地址

# Java Classpath (include wrapper.jar)  Add class path elements as
#  needed starting from 1
wrapper.java.classpath.1=lib/mycatExtend.jar
wrapper.java.classpath.2=lib/wrapper.jar
wrapper.java.classpath.3=conf
wrapper.java.classpath.4=%REPO_DIR%
這樣就大功告成啦~~~啓動mycat!問題修復!!!!!

原文地址https://my.oschina.net/u/3736786/blog/3221601

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章