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();
現在我們需要改成
以及在這個類的clearResources方法裡面,我們需要加上鎖
if(dataMergeSvr!=null){
dataMergeSvr.clear();
}
現在改成
lock.lock();
try{
}finally{
這樣改完後,我們就保證了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