分庫分表(2) --- ShardingSphere(理論)


ShardingSphere---理論

ShardingSphere在中小企業需要分庫分表的時候用的會比較多,因為它維護成本低,不需要額外增派人手;而且目前社區也還一直在開發和維護,還算是比較活躍。

但是中大型公司一般會選擇選用 Mycat 這類 proxy 層方案,因為可能大公司系統和項目非常多,團隊很大,人員充足,那么最好是專門弄個人來研究和維護 Mycat,

然后大量項目直接透明使用即可。

一、ShardingSphere概念

1、概念

ShardingSphere是一套開源的分布式數據庫中間件解決方案組成的生態圈,它由Sharding-JDBCSharding-ProxySharding-Sidecar這3款相互獨立的產品組成。

他們均提供標准化的數據分片分布式事務數據庫治理功能,可適用於如Java同構、異構語言、雲原生等各種多樣化的應用場景。

如圖

2、功能列表

數據分片

- 分庫 & 分表
- 讀寫分離
- 分片策略定制化
- 無中心化分布式主鍵

分布式事務

- 標准化事務接口
- XA強一致事務
- 柔性事務

數據庫治理

- 配置動態化
- 編排 & 治理
- 數據脫敏
- 可視化鏈路追蹤
- 彈性伸縮(規划中)

3、項目狀態


二、分庫分表---結果歸並

概念 將從各個數據節點獲取的多數據結果集,組合成為一個結果集並正確的返回至請求客戶端,稱為結果歸並

我們在實現分庫分表之后,遍歷排序分組分頁聚合 操作變成不在一張表上進行SQL,而是多張表執行的結果進行歸並。

所以我們來看下ShardingSphere實現這些操作的原理。

1、遍歷歸並

它是最為簡單的歸並方式。 只需將多個數據結果集合並為一個單向鏈表即可。在遍歷完成鏈表中當前數據結果集之后,將鏈表元素后移一位,繼續遍歷下一個數據結果集即可。

2、排序歸並

由於在SQL中存在ORDER BY語句,每個數據結果集自身是有序的,所以我們要做的就是對多個有序的數組進行排序

ShardingSphere在對排序的查詢進行歸並時,將每個結果集的當前數據值進行比較(通過實現Java的Comparable接口完成),並將其放入優先級隊列

每次獲取下一條數據時,只需將隊列頂端結果集的游標下移,並根據新游標重新進入優先級排序隊列找到自己的位置即可

舉例

下圖是一個通過分數進行排序的示例圖。 圖中展示了3張表返回的數據結果集,每個數據結果集已經根據分數排序完畢,但是3個數據結果集之間是無序的。

將3個數據結果集的當前游標指向的數據值進行排序,並放入優先級隊列,t_score_0的第一個數據值最大,t_score_2的第一個數據值次之,t_score_1的第一個數據值最小,

因此優先級隊列根據t_score_0,t_score_2和t_score_1的方式排序隊列。

如圖

下圖則展現了進行next調用的時候,排序歸並是如何進行的。 通過圖中我們可以看到,當進行第一次next調用時,排在隊列首位的t_score_0將會被彈出隊列,並且將當前

游標指向的數據值(也就是100)返回至查詢客戶端,並且將游標下移一位(90)之后,重新放入優先級隊列。根據當前數值,t_score_0排列在隊列的最后一位。 之前隊列中

排名第二的t_score_2的數據結果集則自動排在了隊列首位。

在進行第二次next時,只需要將目前排列在隊列首位的t_score_2彈出隊列,並且將其數據結果集游標指向的值返回至客戶端,並下移游標,繼續加入隊列排隊,以此類推。

當一個結果集中已經沒有數據了,則無需再次加入隊列。

可以看到,ShardingSphere的排序歸並,是在維護數據結果集的縱軸和橫軸這兩個維度的有序性

縱軸是指每個數據結果集本身,它是天然有序的,它通過包含ORDER BY的SQL所獲取。

橫軸是指每個數據結果集當前游標所指向的值,它需要通過優先級隊列來維護其正確順序。 每一次數據結果集當前游標的下移都需要將該數據結果集重新放入優先級隊列排序,

而只有排列在隊列首位的數據結果集才可能發生游標下移的操作。

3 、分組歸並

分組歸並的情況最為復雜,它分為流式分組歸並內存分組歸並。 流式分組歸並要求SQL的排序項與分組項的字段以及排序類型(ASC或DESC)必須保持一致,否則只能

通過內存歸並才能保證其數據的正確性。

舉例

假設根據科目分片,表結構中包含考生的姓名(為了簡單起見,不考慮重名的情況)和分數。通過SQL獲取每位考生的總分,可通過如下SQL:

SELECT name, SUM(score) FROM t_score GROUP BY name ORDER BY name;

在分組項與排序項完全一致的情況下,取得的數據是連續的,分組所需的數據全數存在於各個數據結果集的當前游標所指向的數據值,因此可以采用流式歸並。如下圖所示

進行歸並時,邏輯與排序歸並類似。 下圖展現了進行next調用的時候,流式分組歸並是如何進行的。

通過圖中我們可以看到,當進行第一次next調用時,排在隊列首位的t_score_java將會被彈出隊列,並且將分組值同為“Jetty”的其他結果集中的數據一同彈出隊列。 在獲取了

所有的姓名為“Jetty”的同學的分數之后,進行累加操作,那么,在第一次next調用結束后,取出的結果集是“Jetty”的分數總和。 與此同時,所有的數據結果集中的游標都將

下移至數據值“Jetty”的下一個不同的數據值,並且根據數據結果集當前游標指向的值進行重排序。 因此,包含名字順着第二位的“John”的相關數據結果集則排在的隊列的前列。

流式分組歸並與排序歸並的區別僅僅在於兩點:

- 它會一次性的將多個數據結果集中的分組項相同的數據全數取出。
-  它需要根據聚合函數的類型進行聚合計算。

4、聚合歸並

無論是流式分組歸並還是內存分組歸並,對聚合函數的處理都是一致的。 除了分組的SQL之外,不進行分組的SQL也可以使用聚合函數。 因此,聚合歸並是在之前介紹的歸並類

的之上追加的歸並能力,即裝飾者模式聚合函數可以歸類為比較、累加和求平均值這3種類型

比較類型的聚合函數是指MAXMIN。它們需要對每一個同組的結果集數據進行比較,並且直接返回其最大或最小值即可。

累加類型的聚合函數是指SUMCOUNT。它們需要將每一個同組的結果集數據進行累加。

求平均值的聚合函數只有AVG。它必須通過SQL改寫的SUMCOUNT進行計算,相關內容已在SQL改寫的內容中涵蓋,不再贅述。

5、分頁歸並

上文所述的所有歸並類型都可能進行分頁。 分頁也是追加在其他歸並類型之上的裝飾器,ShardingSphere通過裝飾者模式來增加對數據結果集進行分頁的能力。 分頁歸並負責

將無需獲取的數據過濾掉。

ShardingSphere的分頁功能比較容易讓使用者誤解,用戶通常認為分頁歸並會占用大量內存。 在分布式的場景中,將LIMIT 10000000, 10改寫為LIMIT 0, 10000010

才能保證其數據的正確性。 用戶非常容易產生ShardingSphere會將大量無意義的數據加載至內存中,造成內存溢出風險的錯覺。 其實,通過流式歸並的原理可知,會將

數據全部加載到內存中的只有內存分組歸並這一種情況。 而通常來說,進行OLAP的分組SQL,不會產生大量的結果數據,它更多的用於大量的計算,以及少量結果產出的場景。

除了內存分組歸並這種情況之外,其他情況都通過流式歸並獲取數據結果集,因此ShardingSphere會通過結果集的next方法將無需取出的數據全部跳過,並不會將其存入內存。

但同時需要注意的是,由於排序的需要,大量的數據仍然需要傳輸到ShardingSphere的內存空間。 因此,采用LIMIT這種方式分頁,並非最佳實踐。 由於LIMIT並不能通過索引

查詢數據,因此如果可以保證ID的連續性,通過ID進行分頁是比較好的解決方案,例如:

SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id;

或通過記錄上次查詢結果的最后一條記錄的ID進行下一頁的查詢,例如:

SELECT * FROM t_order WHERE id > 10000000 LIMIT 10;

6、總結

用最后一張圖來總結歸並引擎的整體結構划分

補充 有關ShardingSphere其它的知識概述這里就不在講了,這篇文章也是完全根據官方文檔加上個人理解寫的,所以想想要更加詳細的了解可以去看官網。


參考

1、ShardingSphere中文文檔

2、ShardingSphere官網

3、Shardingsphere Github庫



 我相信,無論今后的道路多么坎坷,只要抓住今天,遲早會在奮斗中嘗到人生的甘甜。抓住人生中的一分一秒,勝過虛度中的一月一年!(17)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM