網(wǎng)易私有云的出現(xiàn)為DDB的思變提供了契機(jī),從12年開始,我們就在基于網(wǎng)易私有云開發(fā)一套平臺(tái)化的管理工具cloudadmin,為此,我們將DDB中原先master的功能打散,一部分分庫相關(guān)功能集成到Proxy中,如分庫管理,表管理,用戶管理等,一部分中心化功能集成到cloudadmin中,如報(bào)警監(jiān)控,此外,cloudadmin中提供了一鍵部署,自動(dòng)和手動(dòng)備份,版本管理等平臺(tái)化功能。私有云DDB的整體架構(gòu)如下圖所示:
私有云DDB架構(gòu)
在云DDB解決方案中,還打包了網(wǎng)易私有云LVS服務(wù),cloudadmin通過DDBAgent實(shí)現(xiàn)一鍵部署和報(bào)警監(jiān)控。到目前為止,網(wǎng)易80%以上的DDB集群都已部署云端,云DDB的出現(xiàn)極大減輕了運(yùn)維人員的負(fù)擔(dān)。
DDB特性介紹
分布式執(zhí)行計(jì)劃
分布式執(zhí)行計(jì)劃定義了SQL在分庫分表環(huán)境中各個(gè)數(shù)據(jù)庫節(jié)點(diǎn)上執(zhí)行的方法,順序以及合并規(guī)則,是DDB實(shí)現(xiàn)中最為復(fù)雜的一環(huán)。
如SQL:select * from user order by id limit 10 offset 10;
這個(gè)SQL要查詢id排名在10—20之間的user信息,這里涉及到兩個(gè)合并操作:全局id排序和全局limit offset。對(duì)全局id排序,DDB的做法是將id排序下發(fā)給各個(gè)數(shù)據(jù)庫節(jié)點(diǎn),在DBI層再進(jìn)行一層歸并排序,這樣可以充分利用數(shù)據(jù)庫節(jié)點(diǎn)的計(jì)算資源,同時(shí)將中間件層的排序復(fù)雜度降到最低,例如一些需要用到臨時(shí)文件的排序場(chǎng)景,如果在中間件做全排序會(huì)導(dǎo)致極大開銷。
對(duì)全局limit offset,DDB的做法是將offset累加到limit中下發(fā),因?yàn)閱蝹€(gè)數(shù)據(jù)節(jié)點(diǎn)中的offset是沒有意義的,且會(huì)造成錯(cuò)誤的數(shù)據(jù)偏移,只有在中間件層的全局offset才能保證offset的準(zhǔn)確性。
所以最后下發(fā)的給各個(gè)DBN的SQL變?yōu)椋簊elect * from user order by id limit 20。
又如SQL:select avg(age) from UserTet group by name
可以通過explain語法得到SQL的執(zhí)行計(jì)劃,如下圖所示:
explain示例
上述SQL包含group by分組和avg聚合兩種合并操作,與全局order by類似,group by也可以下發(fā)給數(shù)據(jù)節(jié)點(diǎn),中間件層做一個(gè)歸并去重,但是前提要將group by的字段同時(shí)作為order by字段下發(fā),因?yàn)闅w并的前提是排序。對(duì)avg聚合,不能直接下發(fā),因?yàn)榈玫剿袛?shù)據(jù)節(jié)點(diǎn)各自的平均值,不能求出全局平均值,需要在DBI層把a(bǔ)vg轉(zhuǎn)化為sum和count再下發(fā),在結(jié)果集合并時(shí)再求平均。
DDB執(zhí)行計(jì)劃的代價(jià)取決于DBI中的排序,過濾和連接,在大部分場(chǎng)景下,排序可以將order by下發(fā)來簡(jiǎn)化為一次性歸并排序,這種情況下代價(jià)較小,但是對(duì)group by和order by同時(shí)存在的場(chǎng)景,需要優(yōu)先下發(fā)group by字段的排序,以達(dá)到歸并分組的目的,這種情況下,就需要將所有元素做一次全排序,除非group by和order by的字段相同。
DDB的連接運(yùn)算有兩種實(shí)現(xiàn),第一種是將連接直接下發(fā),若連接的兩張表數(shù)據(jù)分布完全相同,并且在分區(qū)字段上連接,則滿足連接直接下發(fā)的條件,因?yàn)樵诓煌瑪?shù)據(jù)節(jié)點(diǎn)的分區(qū)字段必然沒有相同值,不會(huì)出現(xiàn)跨庫連接的問題。若不滿足連接下發(fā)條件,會(huì)在DBI內(nèi)部執(zhí)行nest loop算法,驅(qū)動(dòng)表的順序與from表排列的次序一致,此時(shí)若出現(xiàn)order by表次序與表排列次序不一致,則不滿足order by下發(fā)條件,也需要在DBI內(nèi)做一次全排序。
分庫分表的執(zhí)行計(jì)劃代價(jià)相比單機(jī)數(shù)據(jù)庫而言,更加難以掌控,即便是相同的SQL模式,在不同的數(shù)據(jù)分布和分區(qū)字段使用方式上,也存在很大的性能差距,DDB的使用要求開發(fā)者和DBA對(duì)執(zhí)行計(jì)劃的原理具有一定認(rèn)識(shí)。
如分庫分表在分區(qū)字段的使用上很有講究:一般建議應(yīng)用中80%以上的SQL查詢通過分區(qū)字段過濾,使SQL可以單庫執(zhí)行。對(duì)于那些沒有走分區(qū)字段的查詢,需要在所有數(shù)據(jù)節(jié)點(diǎn)中并行下發(fā),這對(duì)線程和CPU資源是一種極大的消耗,伴隨著數(shù)據(jù)節(jié)點(diǎn)的擴(kuò)展,這種消耗會(huì)越來越劇烈。另外,基于分區(qū)字段跨庫不重合的原理,在分區(qū)字段上的分組,聚合,distinct,連接等操作,都可以直接下發(fā),這樣對(duì)中間件的代價(jià)往往是最小的。