天天看點

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();

現在我們需要改成

以及在這個類的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