官網:
mycat是乙個開源的分布式資料庫系統,是乙個實現了 mysql 協議的的 server,前端使用者可以把它看作是乙個資料庫**,用 mysql 客戶端工具和命令列訪問,而其後端可以用mysql 原生(native)協議與多個 mysql 伺服器通訊,也可以用 jdbc 協議與大多數主流資料庫伺服器通訊,其核心功能是分表分庫,即將乙個大表水平分割為 n 個小表,儲存在後端 mysql 伺服器裡或者其他資料庫裡。
mycat 是乙個近似等於 mysql 的資料庫伺服器,但它本身並不儲存資料,資料是在後端的 mysql 上儲存的,資料可靠性以及事務等都是 mysql 保證的。你可以用連線 mysql 的方式去連線 mycat(除了埠不同,預設的 mycat 埠是 8066 而非 mysql 的 3306,因此需要在連線字串上增加埠資訊),大多數情況下,可以用你熟悉的物件對映框架使用 mycat,但建議對於分片表,盡量使用基礎的 sql 語句,因為這樣能達到最佳效能,特別是幾千萬甚至幾百億條記錄的情況下。
mycat 的原理並不複雜,複雜的是**。mycat 的原理中最重要的乙個動詞是「攔截」,它攔截了使用者傳送過來的 sql 語句,首先對 sql 語句做了一些特定的分析:如分片分析、路由分析、讀寫分離分析、快取分析等,然後將此 sql 發往後端的真實資料庫,並將返回的結果做適當的處理,最終再返回給使用者。
當 mycat 收到乙個 sql 時,會先解析這個 sql,查詢涉及到的表,然後看此表的定義,如果有分片規則,則獲取到 sql 裡分片欄位的值,並匹配分片函式,得到該 sql 對應的分片列表,然後將 sql 發往這些分片去執行,最後收集和處理所有分片返回的結果資料,並輸出到客戶端。
1. 非分片字段查詢
mycat中的路由結果是通過分片欄位和分片方法來確定的。
如果查詢條件中有分片字段,查詢會通過計算路由落到某個具體的分片,並將請求路由到指定的資料庫上執行。
如果查詢條件中沒有分片字段條件,此時mycat無法計算路由,便傳送到所有節點上執行。如果db節點很多,這會極大消耗mycat和mysql資料庫資源。
2. 分頁排序
先看一下mycat是如何處理分頁操作的,假如有如下mycat分庫方案:
一張表有30份資料分布在3個分片db上,具體資料分布如下:
db1:[0,1,2,3,4,10,11,12,13,14]這個示例的場景中沒有查詢條件,所以都是全分片查詢,也就沒有假定該錶的分片欄位和分片方法。db2:[5,6,7,8,9,16,17,18,19]
db3:[20,21,22,23,24,25,26,27,28,29]
當應用執行如下分頁查詢時:
selectmycat將該sql請求分發到各個db節點去執行,並接收各個db節點的返回結果:* fromtable limit 2;
db1: [0,1]但mycat向應用返回的結果集取決於哪個db節點最先返回結果給mycat。如果mycat最先收到db1節點的結果集,那麼mycat返回給應用端的結果集為 [0,1],如果mycat最先收到db2節點的結果集,那麼返回給應用端的結果集為 [5,6]。也就是說,相同情況下,同乙個sql,在mycat上執行時會有不同的返回結果。db2: [5,6]
db3: [20,21]
在mycat中執行分頁操作時必須顯示加上排序條件才能保證結果的正確性,下面看一下mycat對排序分頁的處理邏輯。
假如在前面的分頁查詢中加上了排序條件(假如表資料的列名為id):
select在有排序呢條件的情況下,mycat接收到各個db節點的返回結果後,對其進行最小堆運算,計算出所有結果集中最小的兩條記錄 [0,1] 返回給應用。* fromtable orderby id limit 2;
但是,當排序分頁中有 偏移量 (offset)時,處理邏輯又有不同。假如應用的查詢sql如下:
select如果按照上述排序分頁邏輯來處理,那麼處理結果如下圖:* fromtable order
by id limit 5,2;
mycat將各個db節點返回的資料 [10,11],[16,17], [20,21] 經過最小堆計算後返回給應用的結果集是 [10,11]。可是,對於應用而言,該錶的所有資料明明是 0-29 這30個資料的集合,limit 5,2 操作返回的結果集應該是 [5,6],如果返回 [10,11] 則是錯誤的處理邏輯。
所以mycat在處理 有偏移量的排序分頁 時是另外一套邏輯——改寫sql 。
mycat在下發有 limit m,n 的sql語句時會對其進行改寫,改寫成 limit 0, m+n 來保證查詢結果的邏輯正確性。所以,mycat傳送到後端db上的sql語句是:
select各個db返回給mycat的結果集是:* fromtable order
by id limit 0,7;
db1: [0,1,2,3,4,10,11]經過最小堆計算後得到最小序列 [0,1,2,3,4,5,6] ,然後返回偏移量為5的兩個結果為 [5,6] 。db2: [5,6,7,8,9,16,17]
db3: [20,21,22,23,24,25,26]
雖然mycat返回了正確的結果,但是仔細推敲發現這類操作的處理邏輯是及其消耗(浪費)資源的。應用需要的結果集為2條,mycat中需要處理的結果數為21條。也就是說,對於有 t 個db節點的全分片 limit m, n 操作,mycat需要處理的資料量為 (m+n)*t 個。比如實際應用中有50個db節點,要執行limit 1000,10操作,則mycat處理的資料量為 50500 條,返回結果集為10,當偏移量更大時,記憶體和cpu資源的消耗則是數十倍增加。
3. 任意表的join
先看一下在單庫中join中的場景。假設在某單庫中有 player 和 team 兩張表,player 表中的 team_id 欄位與 team 表中的id 字段相關聯。
join操作的sql如下:
selectp_name,t_name from player p, team t where p.no =此時能查詢出結果。3and p.team_id = t.id;
這個sql在各個單獨的分片db中都查不出結果,也就是說mycat不能查詢出正確的結果集。
4. 分布式事務
mycat並沒有根據二階段提交協議實現 xa事務,而是只保證 prepare 階段資料一致性的 弱xa事務 ,實現過程如下:
應用開啟事務後mycat標識該連線為非自動提交,比如前端執行:
mysql>mycat不會立即把命令傳送到db節點上,等後續下發sql時,mycat從連線池獲取非自動提交的連線去執行。begin;
mycat會等待各個節點的返回結果,如果都執行成功,mycat給該連線標識為 prepare ready 狀態,如果有乙個節點執行失敗,則標識為 rollback 狀態。
執行完成後mycat等待前端傳送 commit 或 rollback 命令。傳送 commit 命令時,mycat檢測當前連線是否為 prepare ready 狀態,若是,則將 commit 命令傳送到各個db節點。
但是,這一階段是無法保證一致性的,如果乙個db節點在 commit 時故障,而其他db節點 commit 成功,mycat會一直等待故障db節點返回結果。mycat只有收到所有db節點的成功執行結果才會向前端返回 執行成功 的包,此時mycat只能一直 waiting 直至timeout,導致事務一致性被破壞。
本系列是基於1.6-release(2.0尚在開發)
參考:
TiDB適用場景和不適用場景
一 tidb簡介 tidb 是 pingcap 公司受 google spanner f1 啟發而設計的開源分布式 htap hybrid transactional and analytical processing 資料庫,結合了傳統的 rdbms 和nosql 的最佳特性。tidb 相容 my...
HDFS適用場景和不適用場景
海量資料儲存 hdfs可橫向擴充套件,其儲存的檔案可以支援pb級別或更高階別的資料儲存。高容錯性 資料儲存多個副本,副本丟失後自動恢復。可構建在廉價的機器上,實現線性擴充套件。當集群增加新節點之後,namenode也可以感知,進行負載均衡,將資料分發和備份資料均衡到新的節點上。商用硬體 hadoop...
TiDB 的適用場景和不適用場景
典型的oltp場景 當您需要對海量資料 數十億行 進行隨機 實時讀 寫訪問時 實時 htap 場景 實時htap 混合事務 分析處理 要是有乙個使用tidb的類似oltp的場景,並且希望在tiflash的幫助下原地進行 olap分析時,新鮮的資料,對oltp效能無干擾 資料整合 有多個資料來源時,可...