Mycat分庫分表核心技術分析

一、線程模型

1.一、Reactor多線程前端

1.二、處理流程mysql

1) NIOAccetpor中的Selector只接收SocketChannelaccept事件;
2) 
NIOReactor[]數組中依次獲取一個NIOReactor;
3) 將此
SocketChannel放到對應NIOReactor中的Queue中;
4) 
NIOReactor新建的Thread,不斷循環將Queue中的SocketChannel取出並註冊到當前NIOReactor關聯的Selector上面;
5) 
不斷循環Selector返回的SelectionKey進行數據讀取;
6) 
DirectByteBufferPoll分配一塊內存(trunk=4k);
7) 
讀取SocketChannel中的數據,若是一個trunk能夠讀完數據則進行認證、mysql協議解析,encode、並調用對應的handler處理。不然計算報文的長度根據size分配足夠的內存,並將以前讀取的數據copy進來,繼續讀取直至讀完。sql

1.三、流程圖數據庫

1.四、優勢後端

1) 一個NIOAcceptor(聚合了一個Selector,一個線程)能夠處理成百上千的客戶端鏈接,每當有一個新的客戶端鏈接時,就從NIOReactor[]數組中順序獲取一個NIOReactor,當達到數組上限時從新返回0,基本保障了NIOReactor間的負載均衡。
2) 
經過NIOReactor[]線程組實現了串行化線程水平並行執行,線程之間沒有交集,充分利用多核提高並行處理能力。
3) 
NIOReactor[]線程組互不影響,起到故障隔離做用。
4) 
報文的讀取、解析、編碼、以及後續Handler的執行,始終都在一個NIOReactor IO線程上面操做,避免了線程上下文切換和併發修復的風險。數組

1.五、缺點網絡

1) 維護性差:IO線程和handler業務線程爲同一個線程,一旦handler處理(認證、解析、PS渲染、SQL解析、SQL路由)出現延遲,這些延遲毛刺定位難度很大。多線程

1.六、思考併發

1、爲何不使用主從Reactor?
2
、爲何或怎麼能夠把IO線程和業務Handler分開?負載均衡

二、內存管理

DirectByteBufferPool啓動時向系統申請固定數量(PROCESSORS * 20),大小(512 * 4096)同樣的連續內存空間用於建立ByteBufferPageByteBufferPage被切分爲固定大小的trunk(4096)經過BitSet位圖進行內存的分配和回收,1表明已使用,0表明未使用,在每一個ByteBufferPage上面經過AtomicBoolean實現併發控制。

2.一、分配流程

1) 根據size計算須要的trunk數量,塊連續分配,size<4K則分配一個trunk;
2) 
根據上次分配的Page+1,依次從ByteBufferPage[]中取出一個進行分配,報錯分配分配相對均衡,同時必定程度上緩解了線程間的競爭。
3) 
分配時先對ByteBufferPage經過AtomicBoolean進行加鎖,找到符合數量(BitSet0)的連續空間,經過ByteBufferlimit()position()以及slice()進行分配,同時將對應的BitSet位圖置爲1,若是找不到則去下個Page中分配;
4) 
若是都沒有空間,則再分配異常,再沒有則使用HeapByteBuffer

2.二、優勢

1) DirectByteBuffer的分配和釋放比堆內慢10-20倍,進行池化能夠快速分配內存;
2) 
池化技術可使對象複用,下降GC頻率。
3) 
trunk塊大小相同,BitSet位圖內存分配和回收簡單;
4) 
作爲全局數據,經過設置ByteBufferPage[]數量,緩解多線程環境下的鎖競爭;

2.三、缺點

1) 一次性申請完成以後,不能動態擴展;
2) 
固定大小內存,管理的粒度很粗,碎片較大;

2.四、Netty內存管理

Netty內存池的層級結構主要分爲,ArenaChunkListChunkPage、SubPage
Arena
:表明一個內存區域,內存池由Arena[]數組組成,分配時每一個線程按照輪訓策略選擇一個Arena分配。一個Arena由兩個PoolSubPageChunkList雙向鏈表組成。
ChunkList
:由多個Chunk組成的雙向鏈表,可動態變化。
Chunk
:每一個Chunk由默認由2048Page組成。
Page
:大小固定,默認8K,經過徹底二叉樹管理Page的分配和釋放。
SubPage
:大小不固定,又分爲tinySubPage,區間[16,512)smallSubPage區間[512,4096),經過位圖分配和釋放。

三、Druid SQL Parser

代碼結構:

1Parser:將SQL轉換成AST(抽象語法樹),包括Parser(語法解析)和Lexer(詞法解析)
2
AST(Abstract Syntax Tree)
3
Visitor:遍歷AST的工具
4
、執行流程:詞法解析(SQL詞庫) -> 語法解析(校驗是否符合語法邏輯,如from 後面要跟表名) -> 輸出AST

 

四、鏈接池

4.一、定時任務

1) 後端鏈接檢測:SQL執行超時(300s)檢查、Idle檢查;
2) 
前端鏈接檢測:Idle檢查(默認30min);
3) 後端鏈接健康心跳檢測:鏈接是否正常(被對端關閉,網絡斷開重連等),維持最小鏈接;
4) 
數據節點DataHost心跳檢測:檢測datasource是否可用;
5) 
全局表一致性檢測:數據量是否一致;

五、優化和將來

5.一、優化

1) 聚焦而不是膨脹,核心功能和業務需求以前的平滑;
2) 提高統一內存池管理效率,緩解多線程分配時的鎖競爭,減小內存碎片;
3) 
雜亂的ScheduledExecutorService定時任務(10個)打亂了NIOReactor串行化設計思想,形成了沒有必要的線程上下文切換,可統一管理這些定時任務,參考Netty中的時間輪定時任務;

5.二、將來

一、多維度、立體化、全方位監控體系;
二、便捷、易用的管控運維平臺;
3
、分佈式數據庫(動態擴容、Percolator分佈式事務);

 

Ref:

http://www.javashuo.com/article/p-wtfscydu-cy.html

https://www.jianshu.com/p/8d894e42b6e6

https://www.jianshu.com/p/2652686a43eb

相關文章
相關標籤/搜索