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!問題修復!!!!!