日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

mysql多实例访问代理_MySql-Proxy之多路结果集归并

發(fā)布時間:2024/9/27 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql多实例访问代理_MySql-Proxy之多路结果集归并 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MySql-Proxy之多路結(jié)果集歸并

筆者覺得Cobar之類的分庫分表最神奇的部分就是靠一條sql查詢不同schema下(甚至不同實例下)的不同的表。例如

select * from t_test; // 映射為

|------select * from schema1.t_test

|------select * from schema2.t_test

ResultSet // 返回結(jié)果集為兩者的歸并

|--schema1.t_test.ResultSet

|--schema2.t_test.ResultSet

以筆者這種刨根到底的性格當然要把這個過程DIY出來。

由于Cobar對MySql的連接是BIO的。而筆者喜歡NIO,于是用NIO將Corbar的多節(jié)點查詢?nèi)恐貙?基于Netty)。NIO的難度更大,性能也更好,這個重寫的過程就記錄成博客,以饗讀者。

多路歸并原理

多節(jié)點發(fā)送select語句

當客戶端發(fā)送給select * from test后,Lancelot會根據(jù)配置將語句將當前語句路由到多個不同的DB實例上,如上圖所示。

FrontEnd:用來和client交互,一個FrontEnd可以對應(yīng)多個Backend

BackEnd:用來和DB交互

多節(jié)點歸并結(jié)果集

每條語句在一個DB實例上面執(zhí)行后,都會返回一個ResultSet結(jié)果集,在此需要將多個結(jié)果集歸并成一個統(tǒng)一的結(jié)果集,然后返回給client,這樣client就感覺像查詢一個DB實例一樣。

如上圖所示,歸并過程在下面講解。

歸并ResultSet結(jié)果集

在講如何歸并前,我們需要重溫一下MySql返回結(jié)果集的結(jié)構(gòu), 其詳細描述見筆者博客:

https://my.oschina.net/alchemystar/blog/834150

其協(xié)議格式如下所示:

由上圖可見,

其中的Row才是真正的數(shù)據(jù)內(nèi)容。而其余的例如,field_count、fields 、eof以及l(fā)ast_eof則僅僅是攜帶數(shù)據(jù)格式的信息。

如果要多路歸并成一路的話,field_count、fields、eof以及l(fā)ast_eof這些只需要返回給client一份即可。

去掉多余的結(jié)構(gòu)描述信息

現(xiàn)在根據(jù)協(xié)議結(jié)構(gòu)將Frontend歸并結(jié)果集的代碼階段分為三個:

(1)fieldList階段: 由于field_count、fields、eof這三個階段是連續(xù)的,于是將其合并成一個狀態(tài)。

(2)Row階段:顧名思義,接收DB返回的數(shù)據(jù)階段。

(3)LastEof階段:最后的收尾階段,每個結(jié)果集的last_eof表示此結(jié)果集的結(jié)束,只有所有的last_eof都收到之后才能表示結(jié)果的結(jié)束。

fieldList階段的處理:

首先每個Backend都接收field_count,fields,eof。當其接收到eof之后,收到row之前,向Frontend提交這些信息。如下圖所示:

當Frontend獲取到Backend1的feilds信息之后,就開始接收Row,并丟棄其余Backend的fields信息。代碼如下:

public void fieldListResponse(List fieldList) {

lock.lock();

try {

if(!isFailed.get()) {

// 如果還沒有傳過fieldList的話,則傳遞

if (!fieldEofReturned) {

writeFiledList(fieldList);

fieldEofReturned = true;

}

}

} finally {

lock.unlock();

}

}

Row階段的處理

當Frontend進入Row階段之后,處理比較簡單,Backend發(fā)送的任何Row都向前段傳輸,如果是Backend的fields信息則丟棄。如下圖所示:

LastEof階段

每當一個Backend收到last_eof之后,表明當前Backend的結(jié)果集已經(jīng)結(jié)束。Frontend需要等所有的Backend結(jié)果集結(jié)束之后,再發(fā)送一個last_eof告訴client,所有的結(jié)果已經(jīng)完了,如下圖所示:

代碼如下所示:

// last eof response

public void lastEofResponse(BinaryPacket bin) {

lock.lock();

try {

logger.info("last eof ");

if (decrementCountBy()) {

if (!isFailed.get()) {

bin.packetId = ++packetId;

logger.info("write eof okay");

bin.write(session.getCtx());

// 如果是自動提交,則釋放session

if(session.getSource().isAutocommit()){

session.release();

}

}else{

notifyFailure();

}

}

} finally {

lock.unlock();

}

}

例子

運行l(wèi)ancelot中的LanceLotServer的main命令,其就自動連接了我本機的MySql。 配置之類的在SystemConfig中進行修改(現(xiàn)在還沒有做到配置文件化)。

我用mysqlclient連接到lancetlot,然后運行select * from test命令。結(jié)果如下圖所示:

公眾號

關(guān)注筆者公眾號,獲取更多干貨文章:

GitHub鏈接

碼云鏈接

原文鏈接

總結(jié)

以上是生活随笔為你收集整理的mysql多实例访问代理_MySql-Proxy之多路结果集归并的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。