日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

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

MySql-Proxy之多路結果集歸并

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

select * from t_test; // 映射為

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

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

ResultSet // 返回結果集為兩者的歸并

|--schema1.t_test.ResultSet

|--schema2.t_test.ResultSet

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

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

多路歸并原理

多節點發送select語句

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

FrontEnd:用來和client交互,一個FrontEnd可以對應多個Backend

BackEnd:用來和DB交互

多節點歸并結果集

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

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

歸并ResultSet結果集

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

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

其協議格式如下所示:

由上圖可見,

其中的Row才是真正的數據內容。而其余的例如,field_count、fields 、eof以及last_eof則僅僅是攜帶數據格式的信息。

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

去掉多余的結構描述信息

現在根據協議結構將Frontend歸并結果集的代碼階段分為三個:

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

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

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

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發送的任何Row都向前段傳輸,如果是Backend的fields信息則丟棄。如下圖所示:

LastEof階段

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

代碼如下所示:

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

}

}

例子

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

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

公眾號

關注筆者公眾號,獲取更多干貨文章:

GitHub鏈接

碼云鏈接

原文鏈接

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。