一,cobar是什么
畫外音:數(shù)據(jù)庫中間件有基于服務端的,也有基于客戶端的,cobar屬于前者。
二,cobar應用場景舉例
邏輯上:
物理上:
三,cobar使用方式
命令行:連dbtest虛擬庫
JDBC:也是連dbtest虛擬庫
查看db:
可看到dbtest1、dbtest2、dbtest3對用戶透明。
查看table:
可看到有tb1和tb2兩張表。
插入一些數(shù)據(jù),對用戶而言,后端的分布式mysql是透明的:
畫外音:從其官網(wǎng)上看,自12年12月之后,cobar就沒有再更新過,官方微博也非常不活躍,不清楚現(xiàn)在它在阿里的使用情況,知道的同學請說一說。
四,cobar不支持什么
五,cobar支持什么
分布式數(shù)據(jù)庫:通過分庫實現(xiàn)
需要注意:不支持將test拆分成test_1,test_2,test_3并放入同一個庫中這樣的拆分方式。
畫外音:后者正是360的atals的做法(atlas只支持單實例單庫分表)。
HA:通過到mysql的心跳實現(xiàn)
畫外音:需要注意,cobar是需要用戶自己來實現(xiàn)負載均衡的,方式有三種:
SQL路由
在分庫的情況下,cobar會從sql中提取partition key列,來判斷SQL被路由到哪一個分庫進行執(zhí)行;如果沒有帶partition key,則會將SQL分發(fā)到所有分庫執(zhí)行。
示例
tb1(id INT)
假設(shè)以id切分數(shù)據(jù),后端分了N個庫:
畫外音:SQL帶上partition key對cobar來說,非常非常重要,并且partition key不支持修改(修改了庫就不對了喲)。
cobar不允許在同一個連接中切換庫。
畫外音:數(shù)據(jù)庫連接和庫是綁定關(guān)系。
不建議通過cobar來執(zhí)行DDL語句。
畫外音:所以建庫,建索引什么的,還是直連mysql自己搞吧。
COBAR自定義語句
查詢cobar節(jié)點的狀態(tài)
cobar允許管理員通過管理命令上線和下線cobar節(jié)點。
查詢cobar集群的狀態(tài)
被定義在一個cobar集群中的cobar節(jié)點之間都會發(fā)送心跳,所謂的心跳就是上面提到的show cobra_status; 這樣的話,就為每一個cobar節(jié)點提供了知道同一個集群內(nèi)的所有cobar信息的機會。當然,被下線,或者心跳超時的cobar節(jié)點的信息不會被顯示出來。
查詢SQL語句的路由情況
SQL語句前加上explain即可知道SQL語句的路由情況。
事務的支持
cobar對單庫保持事務的強一致性。
對分庫保持事務的弱一致性。
分庫后事務提交包含兩個階段:
執(zhí)行階段
:SQL按照規(guī)則被路由到多個分庫,此時發(fā)生錯誤,還能回滾提交階段
:提交階段出錯,無法正確回滾兩個階段之間,執(zhí)行與提交串行處理,階段內(nèi)部各個分庫并行處理。
畫外音:額,基本就是不支持分布式事務。
系統(tǒng)模塊圖
畫外音:從模塊圖來看,cobar的結(jié)構(gòu)還是挺清晰的:
數(shù)據(jù)流圖
數(shù)據(jù)流圖和上述模塊圖對應:
網(wǎng)絡模型
采用異步網(wǎng)絡模型:
結(jié)果合并
會把多個物理庫的結(jié)果集合并,再返回給上游:
八,cobar路由算法
partition key是int時
好辦,直接取模
partition key是string時
f(string) = hash(string) % 1024
假設(shè)分4個庫:
如何擴容:
拆分后:
數(shù)據(jù)非均勻分布路由:
九,cobar對于SQL的轉(zhuǎn)發(fā)
帶partition key單記錄查詢
直接根據(jù)partition key路由。
帶partition key的IN查詢
將IN進行拆分,請求發(fā)到對應多個分庫,然后將結(jié)果集合并。
不帶partition key的where查詢
假設(shè)partition key是user字段,在product字段上的where查詢,會將請求廣播到所有分庫,然后將結(jié)果集合并。
二維partition key
一張表的多個字段同時作為定位庫的拆分字段,仍以上圖的visit(product, user, info)為例,可以以product和user兩個字段來同時來定位庫。
橫坐標product屬性取hash,縱坐標user屬性取hash。
SELECT * FROM visit WHERE product=‘ColaCola’ AND user=‘A’
對于上述業(yè)務需求,同時帶有兩個列作為查詢條件,可以直接定位到庫7。
但是,此時如果只有其中的一個字段作為查詢條件,反而得查詢多個庫,再做聚合:
SELECT * FROM visit WHERE product=‘ColaCola’
對于上述業(yè)務需求,就必須查詢庫3,7,11,15了。
畫外音:不懂為什么要按照雙key來做路由,單key路由,對于雙key的查詢,也沒有增加多少數(shù)據(jù)掃描量啊,加入雙key反而使得某些情況下策略復雜了,帶來的收益也不高。
小結(jié)
對的,對于where,cobar就是這樣的處理方式:
十,cobar的高級特性
JOIN有限的處理
如上,兩個表都進行了分庫,JOIN需求如下:
SELECT * FROM tb1 INNER JOIN tb2
ON tb1.MEMBER_ID=tb2.NAME
結(jié)果集理應如下:
方案一:迭代查詢
FOR row1 IN select * FROM tb1{
ADD(
SELECT* FROM tb2 WHERE
tb2.name = row1.member_id
)TO RESULT
}
畫外音:我去,外層循環(huán)是對tb1中的所有記錄,在tb2來一遍掃描,bt1數(shù)據(jù)量大的情況下,這哪里受得了?
方案二:夸庫索引
對于tb1和tb2存在的潛在JOIN需求,對JOIN列建立夸庫索引。
直接JOIN查詢
:建立了夸庫索引后,對于JOIN的直接查詢,就是idx索引表內(nèi)的數(shù)據(jù)的合并就是結(jié)果JOIN后帶WHERE條件
:SELECT * FROM tb1 INNER JOIN tb2
ON tb1.MEMBER_ID=tb2.NAME
WHEREtb1.id=5
此時需要改寫SQL語句,直接在索引表上進行查詢:
SELECT * FROM idx WHERE id1=5
此處需要注意:
GROUP BY的處理
以上表為例,patition key是ID,要在C1上進行GROUP BY操作:
SELECT SUM(price) FROM tb1 GROUP BY c1;
改寫SQL語句,先在各個分庫上GROUP BY一次,并將sum計算出來:
SELECT SUM(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1;
各分庫進行GROUP BY + ORDER BY + sum之后,根據(jù)排序后的c1及對應sum結(jié)果,歸并一遍后即得到最終結(jié)果。
小結(jié)
對于復雜語句,可以這樣處理: