網(wǎng)易數(shù)據(jù)運(yùn)河系統(tǒng)NDC設(shè)計(jì)與應(yīng)用
NDC是網(wǎng)易近一年新誕生的結(jié)構(gòu)化數(shù)據(jù)傳輸服務(wù),它整合了網(wǎng)易過去在數(shù)據(jù)傳輸領(lǐng)域的各種工具和經(jīng)驗(yàn),將單機(jī)數(shù)據(jù)庫(kù)、分布式數(shù)據(jù)庫(kù)、OLAP系統(tǒng)以及下游應(yīng)用通過數(shù)據(jù)鏈路串在一起。除了保障高效的數(shù)據(jù)傳輸外,NDC的設(shè)計(jì)遵循了單元化和平臺(tái)化的設(shè)計(jì)哲學(xué),本篇文章將帶大家近距離了解NDC的設(shè)計(jì)思路和實(shí)現(xiàn)原理。
NDC簡(jiǎn)介
NDC全名Netease Data Canal,直譯為網(wǎng)易數(shù)據(jù)運(yùn)河系統(tǒng),是網(wǎng)易針對(duì)結(jié)構(gòu)化數(shù)據(jù)庫(kù)的數(shù)據(jù)實(shí)時(shí)遷移、同步和訂閱的平臺(tái)化解決方案。
在NDC之前,我們主要通過自研或開源軟件工具來滿足異構(gòu)數(shù)據(jù)庫(kù)實(shí)時(shí)遷移和同步的需求,隨著云計(jì)算和公司業(yè)務(wù)的大力推進(jìn),公司內(nèi)部,尤其是運(yùn)維團(tuán)隊(duì)開始對(duì)數(shù)據(jù)遷移工具的可用性、易用性以及其他多樣化功能提出了更多要求和挑戰(zhàn),NDC平臺(tái)化解決方案便應(yīng)運(yùn)而生。NDC的構(gòu)建快速整合了我們之前在結(jié)構(gòu)化數(shù)據(jù)遷移領(lǐng)域的積累,于2016年8月正式立項(xiàng),同年10月就已上線開始為我們的各大產(chǎn)品線提供在線數(shù)據(jù)遷移和同步服務(wù)。
業(yè)界中與NDC類似的產(chǎn)品有阿里云的DTS、阿里開源產(chǎn)品DataX、Canal、Twitter的Databus,在傳統(tǒng)領(lǐng)域有Oracle的GoldenGate、開源產(chǎn)品SymmetricDS。從產(chǎn)品功能、成熟度來看,NDC與阿里云DTS最為相似,都具有簡(jiǎn)、快、全三大特性:
- 簡(jiǎn),使用簡(jiǎn)單,有平臺(tái)化的Web管理工具,配置流程簡(jiǎn)潔易懂。
- 快,數(shù)據(jù)同步、遷移和訂閱速度快,執(zhí)行高效,滿足互聯(lián)網(wǎng)產(chǎn)品快速迭代的需求。
- 全,功能齊全,NDC支持多種常用的異構(gòu)數(shù)據(jù)庫(kù),包括Oracle、MySQL、SQLServer、DB2、PostgreSQL以及網(wǎng)易分布式數(shù)據(jù)庫(kù)DDB,除了可以滿足不同數(shù)據(jù)庫(kù)之間在線數(shù)據(jù)遷移、實(shí)時(shí)同步之外,NDC也可以實(shí)現(xiàn)從數(shù)據(jù)庫(kù)到多種OLAP系統(tǒng)的實(shí)時(shí)數(shù)據(jù)同步和ETL,目前同步目標(biāo)支持的OLAP系統(tǒng)包含Kudu和Greeplum。另外,NDC支持對(duì)數(shù)據(jù)庫(kù)做數(shù)據(jù)訂閱,通過將數(shù)據(jù)庫(kù)的增量數(shù)據(jù)丟入消息隊(duì)列,使應(yīng)用端可以自由消費(fèi)數(shù)據(jù)庫(kù)的實(shí)時(shí)增量數(shù)據(jù),從而實(shí)現(xiàn)由數(shù)據(jù)驅(qū)動(dòng)業(yè)務(wù),復(fù)雜業(yè)務(wù)之間調(diào)用解耦。
提煉場(chǎng)景和需求是做好產(chǎn)品的第一步,本文先通過三種典型應(yīng)用場(chǎng)景介紹NDC的使用價(jià)值,之后從產(chǎn)品形態(tài)和系統(tǒng)架構(gòu)兩方面闡述NDC在產(chǎn)品交互、集群管理、資源調(diào)度以及跨機(jī)房部署上的設(shè)計(jì)理念,最后介紹NDC實(shí)現(xiàn)數(shù)據(jù)遷移、同步和訂閱的一些原理和關(guān)鍵特性,可以為開發(fā)者在實(shí)現(xiàn)類似功能時(shí)提供思路和參考。
應(yīng)用場(chǎng)景
下面通過三個(gè)真實(shí)案例分別說明NDC在數(shù)據(jù)遷移和數(shù)據(jù)訂閱上的應(yīng)用場(chǎng)景。
DDB數(shù)據(jù)遷移
分布式數(shù)據(jù)庫(kù)DDB自2006年就開始為網(wǎng)易各大互聯(lián)網(wǎng)產(chǎn)品提供透明的分庫(kù)分表服務(wù),在我們的知名互聯(lián)網(wǎng)產(chǎn)品背后,幾乎都可以看到DDB的身影,如考拉、云音樂、云閱讀、教育等。
DDB作為分庫(kù)分表的結(jié)構(gòu)化數(shù)據(jù)庫(kù),一張表的數(shù)據(jù)一般存儲(chǔ)在多個(gè)數(shù)據(jù)節(jié)點(diǎn)中,每張表會(huì)選擇一個(gè)或多個(gè)字段作為分區(qū)鍵,來決定數(shù)據(jù)在數(shù)據(jù)節(jié)點(diǎn)上的分布方式。以用戶表為例,有用戶ID作為主鍵,電話號(hào)碼和郵箱作為唯一健,分區(qū)鍵一般會(huì)選擇這三個(gè)字段中的任意一個(gè)或組合。分區(qū)鍵的選擇決定了數(shù)據(jù)分布均勻與否,隨著業(yè)務(wù)數(shù)據(jù)量的增長(zhǎng),可能會(huì)發(fā)現(xiàn)之前選擇的分區(qū)鍵區(qū)分度不夠高,而需要更改分區(qū)鍵的需求,分區(qū)鍵的修改涉及到數(shù)據(jù)重分布,并且修改過程要與業(yè)務(wù)的線上服務(wù)同時(shí)進(jìn)行,這就要求DDB提供在線數(shù)據(jù)遷移的解決方案。
與此類似,在業(yè)務(wù)發(fā)展過程中可能遇到表擴(kuò)容或機(jī)房遷移的情況,都需要DDB的在線數(shù)據(jù)遷移功能,以表擴(kuò)容為例,NDC解決DDB在線數(shù)據(jù)遷移方式如圖1所示。
圖1 NDC解決DDB數(shù)據(jù)遷移問題
當(dāng)DBA發(fā)起一個(gè)修改分區(qū)鍵或擴(kuò)容請(qǐng)求時(shí),管理工具會(huì)統(tǒng)一將其解析成一個(gè)數(shù)據(jù)遷移命令,并向NDC服務(wù)發(fā)起相應(yīng)的調(diào)度請(qǐng)求,NDC則根據(jù)調(diào)度規(guī)則選擇一組執(zhí)行節(jié)點(diǎn)執(zhí)行具體遷移過程,每個(gè)源端數(shù)據(jù)節(jié)點(diǎn)都會(huì)有對(duì)應(yīng)一個(gè)遷移進(jìn)程來拉取該節(jié)點(diǎn)上的全量數(shù)據(jù)和增量數(shù)據(jù),并將這些數(shù)據(jù)通過DDB的分庫(kù)分表驅(qū)動(dòng)重新應(yīng)用到目標(biāo)表。當(dāng)目標(biāo)端和源端的數(shù)據(jù)延遲在追趕到毫秒級(jí)范圍內(nèi)后,通過在DDB管理工具上執(zhí)行切換表操作完成最后的遷移工作。
應(yīng)用緩存更新
應(yīng)用緩存更新是NDC數(shù)據(jù)訂閱一類非常典型的應(yīng)用場(chǎng)景,在沒有使用數(shù)據(jù)訂閱做緩存更新的應(yīng)用環(huán)境中,緩存數(shù)據(jù)通常由應(yīng)用服務(wù)器自己維護(hù),但是由于緩存操作和數(shù)據(jù)庫(kù)操作不具有事務(wù)性,簡(jiǎn)單的緩存操作可能帶來數(shù)據(jù)不一致的情況,如圖2所示。
圖2 緩存數(shù)據(jù)庫(kù)不一致問題
在圖2場(chǎng)景中,線程2在將緩存更新到最新數(shù)據(jù)后,又被線程1異步滯后地更新成老數(shù)據(jù),由于線程1和線程2沒有任何狀態(tài)共享,數(shù)據(jù)庫(kù)中后操作的數(shù)據(jù)可能在緩存中被先操作的數(shù)據(jù)覆蓋掉,導(dǎo)致緩存和數(shù)據(jù)庫(kù)數(shù)據(jù)不一致。若這種情況出現(xiàn),除非緩存主動(dòng)淘汰,否則應(yīng)用將始終讀到臟數(shù)據(jù)。
對(duì)上述的數(shù)據(jù)不一致問題,業(yè)界也有一種基于CAS的解決方案,但會(huì)對(duì)緩存增加至少一倍以上的壓力。而通過NDC的數(shù)據(jù)訂閱,可以比較完美地解決上述問題,NDC數(shù)據(jù)訂閱將數(shù)據(jù)庫(kù)中的增量數(shù)據(jù)丟入消息隊(duì)列,應(yīng)用讀取消息隊(duì)列的內(nèi)容,并將其同步到緩存系統(tǒng),在這個(gè)過程中,NDC執(zhí)行節(jié)點(diǎn)和消息隊(duì)列保障高可用,而數(shù)據(jù)庫(kù)增量數(shù)據(jù)具有唯一性和時(shí)序性,可以避免緩存和數(shù)據(jù)庫(kù)的狀態(tài)不一致。
如果說使用數(shù)據(jù)訂閱只是緩存更新的一種優(yōu)選方案的話,那對(duì)下面的多機(jī)房緩存淘汰,NDC的數(shù)據(jù)訂閱功能就是必選方案了。
圖3中,應(yīng)用部署有主機(jī)房和備機(jī)房?jī)商篆h(huán)境,兩套環(huán)境各有一套應(yīng)用服務(wù),緩存和數(shù)據(jù)庫(kù),為了保障主備機(jī)房數(shù)據(jù)一致,數(shù)據(jù)寫入只能走主機(jī)房,備機(jī)房數(shù)據(jù)庫(kù)是主機(jī)房數(shù)據(jù)庫(kù)的只讀從庫(kù),這種架構(gòu)普遍適用于讀多寫少的應(yīng)用系統(tǒng)。
圖3 NDC解決多機(jī)房緩存淘汰問題
在業(yè)務(wù)不適用數(shù)據(jù)訂閱來更新緩存的情況下,從機(jī)房在執(zhí)行刪除數(shù)據(jù)時(shí),先刪除主機(jī)房數(shù)據(jù),再刪除從機(jī)房緩存,而從機(jī)房的數(shù)據(jù)庫(kù)同步具有一定的滯后性,在滯后的這段時(shí)間,從機(jī)房應(yīng)用服務(wù)可能會(huì)將從機(jī)房數(shù)據(jù)庫(kù)的臟數(shù)據(jù)重新載入緩存,導(dǎo)致從機(jī)房應(yīng)用依舊能看到刪除后的數(shù)據(jù)。為此,我們的方案是使用NDC訂閱從機(jī)房數(shù)據(jù)庫(kù)的刪除操作,保障從機(jī)房數(shù)據(jù)庫(kù)和緩存在刪除操作上具有一致性。
OLAP系統(tǒng)整合/ETL
業(yè)務(wù)數(shù)據(jù)庫(kù)與OLAP系統(tǒng)的數(shù)據(jù)整合,是互聯(lián)網(wǎng)產(chǎn)品架構(gòu)中非常重要的一環(huán)。比較傳統(tǒng)的應(yīng)用一般采用定時(shí)從OLTP庫(kù)中將數(shù)據(jù)全量導(dǎo)入OLAP系統(tǒng),比如每天凌晨1點(diǎn)開始把線上MySQL中所有數(shù)據(jù)通過Sqoop導(dǎo)入到Hive。這種做法有極大限制性:首先,ETL的時(shí)間完全不可控,這對(duì)于時(shí)效性比較敏感的數(shù)據(jù)尤為重要;其次ETL過程中對(duì)源庫(kù)負(fù)載壓力非常大,尤其對(duì)數(shù)據(jù)量大的應(yīng)用,而控制ETL對(duì)源端負(fù)載影響就意味著ETL時(shí)間更加失控。
在NDC這樣的系統(tǒng)出現(xiàn)后,架構(gòu)師們有了更加明智的選擇:通過NDC實(shí)現(xiàn)結(jié)構(gòu)化數(shù)據(jù)的增量ETL。首先使ETL從小時(shí)級(jí)延遲降低到秒級(jí),其次NDC的增量數(shù)據(jù)拉取對(duì)源端影響非常小。對(duì)直接支持?jǐn)?shù)據(jù)更新的OLAP系統(tǒng)而言,可以直接通過NDC實(shí)現(xiàn)ETL,如Kudu、HBase。對(duì)于不支持?jǐn)?shù)據(jù)更新的系統(tǒng),如Hive,可以通過NDC的數(shù)據(jù)訂閱功能將數(shù)據(jù)庫(kù)增量數(shù)據(jù)發(fā)布到消息隊(duì)列,再定時(shí)從消息隊(duì)列中獲取增量數(shù)據(jù),并通過MR合并到存量數(shù)據(jù),當(dāng)然這里的定時(shí)要比原先定時(shí)全量的時(shí)間間隔小很多,比如每小時(shí)、每15分鐘——通過這種方式實(shí)現(xiàn)準(zhǔn)實(shí)時(shí)的ETL。
圖4 通過NDC實(shí)現(xiàn)OLAP系統(tǒng)整合與ETL
產(chǎn)品形態(tài)
在產(chǎn)品形態(tài)上,NDC具有平臺(tái)化、可插拔和單元化三大特性。
平臺(tái)化
往前追溯幾年,各種PaaS和SaaS服務(wù)還未如現(xiàn)在這般舉目皆是,運(yùn)維小伙伴還比較習(xí)慣以部署軟件的方式為業(yè)務(wù)方提供各種服務(wù),比如在NDC之前,我們有軟件包Hamal來支持DDB的各種數(shù)據(jù)遷移工作,DBA在實(shí)施DDB擴(kuò)容時(shí),需要經(jīng)歷以下步驟:
- 準(zhǔn)備一定數(shù)量的物理機(jī)或云主機(jī)跑遷移任務(wù);
- 在這些節(jié)點(diǎn)上部署Hamal進(jìn)程,配置源端目標(biāo)端,并發(fā)度等參數(shù);
- 通過Hamal日志或監(jiān)控程序?qū)崟r(shí)查看遷移進(jìn)度;
- 數(shù)據(jù)遷移追趕上線上的數(shù)據(jù)增長(zhǎng)后,完成切表或切庫(kù)操作;
- 回收Hamal進(jìn)程,釋放相關(guān)資源。
隨著負(fù)責(zé)的產(chǎn)品越來越多,規(guī)模越來越大,管理員在不同產(chǎn)品的機(jī)器、配置之間疲于奔命,大量重復(fù)性工作增加了犯錯(cuò)可能,更要命的是遇到資源不足,可能還要經(jīng)歷漫長(zhǎng)的采購(gòu)周期。對(duì)于DBA一類的運(yùn)維人員,迫切需要一套幫助他們解決采購(gòu)、部署、調(diào)度以及任務(wù)完成后的資源回收等一系列運(yùn)維工作的平臺(tái)化管理工具,這便是NDC。
NDC提供有跨IDC的平臺(tái)化Web管理界面和類似云計(jì)算的租戶管理概念,產(chǎn)品管理員在使用NDC時(shí),在產(chǎn)品相關(guān)租戶下創(chuàng)建、修改和刪除具體的數(shù)據(jù)遷移、同步和訂閱任務(wù),由NDC調(diào)度中心將任務(wù)調(diào)度到相關(guān)的執(zhí)行節(jié)點(diǎn)。另外配有專門的平臺(tái)管理員對(duì)NDC整個(gè)平臺(tái)做容量規(guī)劃,NDC管理界面如圖5所。
圖5 NDC管理界面
圖中可以看到,NDC除了提供基本的任務(wù)管理之外,還為管理員提供了大量運(yùn)行時(shí)的監(jiān)控統(tǒng)計(jì)數(shù)據(jù),幫助管理員更好地把控任務(wù)進(jìn)度和狀態(tài)。
可插拔
NDC除了向產(chǎn)品管理員和開發(fā)者直接提供服務(wù)外,同時(shí)也是DDB數(shù)據(jù)遷移、猛犸(網(wǎng)易大數(shù)據(jù)系統(tǒng))數(shù)據(jù)同步的依賴組件,如圖6所示。
圖6 NDC平臺(tái)可插拔特性
在DBA通過DDBAdmin做表擴(kuò)縮容,更改分區(qū)字段等操作時(shí),DDBAdmin會(huì)把請(qǐng)求解析成多個(gè)數(shù)據(jù)遷移任務(wù)提交給NDC。類似的,未來NDC可能還會(huì)支持其他自身有認(rèn)證功能的平臺(tái)系統(tǒng),比如公有云,為此,NDC 需要做到其他平臺(tái)的輕松插拔。
NDC的平臺(tái)插拔特性,本質(zhì)上是要支持不同租戶認(rèn)證的可插拔,因?yàn)橐蕾囉贜DC之上的其他平臺(tái)大都實(shí)有自己的租戶認(rèn)證功能,要求NDC支持這些不同的認(rèn)證方式是不現(xiàn)實(shí)的,我們的做法是“認(rèn)證服務(wù)”,具體的租戶認(rèn)證交由上層平臺(tái)自己完成。與此同時(shí),我們可以按照上層平臺(tái)的租戶名對(duì)任務(wù)做物理隔離和任務(wù)視圖的劃分。租戶可插拔的另外一個(gè)要點(diǎn),是NDC自帶的租戶認(rèn)證需要在API服務(wù)內(nèi)實(shí)現(xiàn),從NDC的調(diào)度中心來看,API服務(wù)與其他平臺(tái)是同一個(gè)架構(gòu)層的不同接入平臺(tái)。
NDC可插拔的另一個(gè)含義是“功能可插拔”。立項(xiàng)至今,NDC前前后后支持了六種關(guān)系型數(shù)據(jù)庫(kù)、三種OLAP系統(tǒng),每種源端和目的端都是通過實(shí)現(xiàn)統(tǒng)一的Extractor和Applier接口來支持,而且我們?cè)贘AR包上做了合理拆分,以便一些功能修改可以獨(dú)立上線。未來對(duì)新的源端目的端的支持也可以通過實(shí)現(xiàn)接口和新增JAR包在不重啟任何進(jìn)程的前提下完成擴(kuò)展。
單元化
可以通過NDC實(shí)現(xiàn)跨機(jī)房的數(shù)據(jù)同步解決方案,尤其對(duì)體量比較大的應(yīng)用,如網(wǎng)易考拉、云音樂,普遍需要在同城甚至異地機(jī)房之間做服務(wù)冗余、擴(kuò)展和容災(zāi)。相對(duì)應(yīng)地,這些應(yīng)用所依賴的底層服務(wù)也需要具備多機(jī)房冗余和擴(kuò)展的功能,如圖7所示。
圖7 NDC跨機(jī)房的單元化解決方案
在一個(gè)機(jī)房?jī)?nèi)的系統(tǒng)架構(gòu)中,應(yīng)用服務(wù)無狀態(tài),緩存、大數(shù)據(jù),這些有狀態(tài)系統(tǒng)的數(shù)據(jù)來自于數(shù)據(jù)庫(kù)的數(shù)據(jù)同步和訂閱,而數(shù)據(jù)庫(kù)的數(shù)據(jù)除了本機(jī)房?jī)?nèi)應(yīng)用產(chǎn)生外,也可以來自NDC從其他機(jī)房的數(shù)據(jù)同步。從這套架構(gòu)中可以看出,通過NDC同步機(jī)房間的數(shù)據(jù)庫(kù)數(shù)據(jù),再由NDC將數(shù)據(jù)庫(kù)的變更同步到大數(shù)據(jù)、緩存、消息隊(duì)列,由此驅(qū)動(dòng)業(yè)務(wù)在機(jī)房間無縫擴(kuò)展和冗余。
在圖7中,每個(gè)機(jī)房?jī)?nèi)從應(yīng)用服務(wù)到數(shù)據(jù)庫(kù),具有一套完整的數(shù)據(jù)鏈路,機(jī)房?jī)?nèi)部的網(wǎng)絡(luò)、IT資源,相關(guān)的各種調(diào)度都具有高度自治性,機(jī)房間的耦合模塊只有通過NDC共享數(shù)據(jù)庫(kù)數(shù)據(jù),業(yè)界目前將這種具備完整服務(wù)鏈路,且高度自治的跨機(jī)房方案稱之為“單元化”,NDC的單元化要求在每個(gè)機(jī)房?jī)?nèi)部署獨(dú)立的調(diào)度中心和執(zhí)行節(jié)點(diǎn)組,需要注意的是,單元化并不包含NDC的API服務(wù),API服務(wù)具有無狀態(tài)、請(qǐng)求離散等特性,沒有必要獨(dú)立部署,同時(shí)跨單元的API才能提供平臺(tái)化的管理服務(wù)。
值得一提的是,所謂“單元”是一個(gè)邏輯概念,一個(gè)單元具有物理隔離和高度自治的特性,我們也可以在一個(gè)機(jī)房?jī)?nèi)部署多個(gè)NDC單元,以區(qū)別和隔離不同業(yè)務(wù)線,比如我們可以為DDB和猛犸部署一套獨(dú)立單元來支撐他們的平臺(tái)依賴,不過一個(gè)單元基本不會(huì)跨機(jī)房部署。
系統(tǒng)架構(gòu)
一個(gè)單元內(nèi)的NDC系統(tǒng)架構(gòu)如圖8所示。
圖8 NDC架構(gòu)圖
最上層無狀態(tài)的API服務(wù),是一套直接面向用戶的平臺(tái)化Web管理工具,API節(jié)點(diǎn)通過RPC向調(diào)度中心Center發(fā)起請(qǐng)求,除了API節(jié)點(diǎn)外,Center也會(huì)接受來自DDB管理工具、猛犸管理工具等其他平臺(tái)的RPC調(diào)用請(qǐng)求。
Center是NDC的大腦,所有管理、調(diào)度、監(jiān)控、報(bào)警工作都需要通過Center來執(zhí)行,Center目前在一個(gè)單元內(nèi)屬于單點(diǎn)服務(wù),通過高可用組件做冷備,由于元數(shù)據(jù)統(tǒng)一存儲(chǔ)在NDC的系統(tǒng)庫(kù)中,主備Center之間無需數(shù)據(jù)同步。Center會(huì)定期收集單元內(nèi)所有Engine節(jié)點(diǎn)的負(fù)載狀況、任務(wù)執(zhí)行狀態(tài)等信息,以實(shí)現(xiàn)均衡的任務(wù)調(diào)度,在任務(wù)失敗時(shí)自動(dòng)重試或重新調(diào)度,保障任務(wù)執(zhí)行具有高可用特性。
Engine是NDC系統(tǒng)中數(shù)據(jù)遷移、同步和訂閱的任務(wù)執(zhí)行者,它接收來自Center的調(diào)度請(qǐng)求,并維護(hù)一組實(shí)際任務(wù)執(zhí)行進(jìn)程Executo。在任務(wù)執(zhí)行過程中,Engine負(fù)責(zé)收集每個(gè)執(zhí)行進(jìn)程的任務(wù)狀態(tài)、進(jìn)度信息,并實(shí)時(shí)上報(bào)給Center。Center不知道任何Executor的存在,任務(wù)執(zhí)行進(jìn)程全權(quán)托管于Engine,并由Engine全程監(jiān)控。
“單元”是NDC物理資源隔離的最大單位,除了基于單元的隔離之外,NDC還提供了租戶級(jí)別的物理隔離,管理員可以為租戶分配獨(dú)占的任務(wù)執(zhí)行節(jié)點(diǎn)。在配置任務(wù)屬性時(shí)選擇“獨(dú)占型”任務(wù),則任務(wù)只會(huì)調(diào)度到屬于該用戶的資源池中,以確保任務(wù)執(zhí)行具有節(jié)點(diǎn)級(jí)別的隔離性,而普通共享型任務(wù)只具備進(jìn)程級(jí)別的隔離性。
實(shí)現(xiàn)簡(jiǎn)述
NDC是面向結(jié)構(gòu)化數(shù)據(jù)庫(kù)的數(shù)據(jù)遷移、同步和訂閱的解決方案,而數(shù)據(jù)同步可以看做一種“永不結(jié)束”的數(shù)據(jù)遷移,下面我們就NDC在數(shù)據(jù)遷移、數(shù)據(jù)訂閱以及一些關(guān)鍵特性上的實(shí)現(xiàn)方式做個(gè)簡(jiǎn)要介紹。
NDC的訂閱和遷移都以表為單位,如無特別說明,下文中的遷移對(duì)象均指要遷移的表。
數(shù)據(jù)遷移
與通常的“遷移”概念不同,NDC的“數(shù)據(jù)遷移”并不是將源端的數(shù)據(jù)挪到目標(biāo)端,而是在保障對(duì)源端數(shù)據(jù)影響盡可能小的前提下,將源端的數(shù)據(jù)“復(fù)制”或“同步”到目標(biāo)端。比如線上數(shù)據(jù)庫(kù)到數(shù)據(jù)倉(cāng)庫(kù)的ETL,需要在不影響線上服務(wù)質(zhì)量的情況下將數(shù)據(jù)實(shí)時(shí)同步到數(shù)據(jù)倉(cāng)庫(kù)。又如DDB的在線擴(kuò)容,也需要在擴(kuò)容的過程中不影響原有的數(shù)據(jù)節(jié)點(diǎn)。
當(dāng)用戶通過Web工具啟動(dòng)一個(gè)數(shù)據(jù)遷移任務(wù)后,NDC調(diào)度服務(wù)會(huì)根據(jù)任務(wù)類型、調(diào)度算法和節(jié)點(diǎn)負(fù)載,在相關(guān)的Engine資源池中選擇一個(gè)或多個(gè)節(jié)點(diǎn)下發(fā)任務(wù),一個(gè)遷移任務(wù)對(duì)應(yīng)一個(gè)源端數(shù)據(jù)庫(kù)實(shí)例。
數(shù)據(jù)遷移引擎中任務(wù)執(zhí)行流程如圖9所示。
圖9 NDC數(shù)據(jù)遷移執(zhí)行流程
從圖中可以看出,全部的數(shù)據(jù)遷移流程包含以下四個(gè)步驟:
- 預(yù)檢查:檢查資源、網(wǎng)絡(luò)可用性、Schema兼容性、用戶權(quán)限等;
- 全量遷移:源庫(kù)、表中存量數(shù)據(jù)的遷移過程;
- 增量遷移:遷移過程中,源庫(kù)、表增量數(shù)據(jù)的遷移過程;
- 數(shù)據(jù)校驗(yàn):對(duì)源端和目標(biāo)端同步的數(shù)據(jù)做抽樣校驗(yàn)。
預(yù)檢查階段,NDC會(huì)檢查源端和目標(biāo)端的網(wǎng)絡(luò)連通性、空余資源可用性、遷移使用的源端目標(biāo)端用戶在相關(guān)庫(kù)表上的權(quán)限、白名單、要遷移的Schema是否兼容等。NDC不要求遷移對(duì)象在源端目標(biāo)端的Schema嚴(yán)格一致,但要求目標(biāo)端對(duì)源端兼容,比如源端字段類型int到目標(biāo)端可以為bigint,反之則預(yù)檢查報(bào)錯(cuò),源端目標(biāo)端在索引結(jié)構(gòu)上允許有差異。
預(yù)檢查完成后,NDC任務(wù)執(zhí)行進(jìn)程會(huì)立即啟動(dòng)增量數(shù)據(jù)拉取模塊,在開始拉增量數(shù)據(jù)之后,啟動(dòng)全量遷移流程。顧名思義,全量遷移是將遷移對(duì)象的存量數(shù)據(jù)同步到目標(biāo)端。NDC的全量數(shù)據(jù)遷移采用“快照讀”,而判斷遷移對(duì)象中哪些數(shù)據(jù)是存量數(shù)據(jù),哪些是增量數(shù)據(jù)的依據(jù),是在開始全量遷移的時(shí)候獲取遷移表的最小主鍵和最大主鍵,在獲取到的最小主鍵和最大主鍵之間的所有數(shù)據(jù),被認(rèn)為是存量數(shù)據(jù),以外則作為增量數(shù)據(jù)處理。之所以沒有像MySQLDump一類的遷移工具使用大事務(wù)來劃分存量數(shù)據(jù),是為了避免大事務(wù)令源端回滾段不斷累加的影響(這是針對(duì)MySQL而言,對(duì)不同類型的源端數(shù)據(jù)庫(kù),大事務(wù)都會(huì)造成一定的不良影響),而使用快照讀,會(huì)使全量遷移過程中引入一部分增量數(shù)據(jù),但這部分增量的“臟數(shù)據(jù)”最終會(huì)被增量遷移修正,不影響數(shù)據(jù)的最終一致性。
全量遷移以表為單位進(jìn)行,不同表之間可并發(fā)遷移,增量遷移則以源端實(shí)例為單位(想想MySQL的binlog),所以在一個(gè)遷移任務(wù)中,所有遷移對(duì)象都完成全量遷移后,才會(huì)進(jìn)入增量遷移階段。
增量遷移至少包含兩個(gè)線程,第一個(gè)是增量數(shù)據(jù)拉取線程,在全量遷移開始之前啟動(dòng),負(fù)責(zé)將源端所有(相關(guān))增量數(shù)據(jù)緩存在本地磁盤;另一個(gè)是增量回放線程,在增強(qiáng)遷移過程開始時(shí)啟動(dòng),它的作用是不斷讀取本地緩存的增量數(shù)據(jù),并按照時(shí)間順序回放到目標(biāo)端。
由于全量遷移是在增量拉取開始之后才進(jìn)行的,NDC可以保障全量遷移過程中引入的增量數(shù)據(jù)最終會(huì)在目標(biāo)端回放出來。
全量遷移和增量遷移過程中會(huì)有一部分增量數(shù)據(jù)被重復(fù)導(dǎo)入,NDC會(huì)保障增量數(shù)據(jù)導(dǎo)入具有冪等性。
隨著增量遷移的進(jìn)行,目標(biāo)端增量數(shù)據(jù)和源端增量數(shù)據(jù)的時(shí)間延遲會(huì)逐漸縮短,最終這個(gè)延遲控制在1s內(nèi)之后,我們將這個(gè)遷移任務(wù)定義為同步狀態(tài)。對(duì)同步狀態(tài)下的遷移任務(wù),管理員可以選擇實(shí)施數(shù)據(jù)校驗(yàn),一般建議采用源端5‰到100‰的隨機(jī)數(shù)據(jù)校驗(yàn)源端和目標(biāo)端的數(shù)據(jù)一致性。
NDC數(shù)據(jù)遷移中的全量遷移、增量遷移以及數(shù)據(jù)校驗(yàn)都是可選流程,不過NDC要求管理員至少勾選全量遷移和增量遷移中的一種,數(shù)據(jù)校驗(yàn)是遷移任務(wù)進(jìn)入同步狀態(tài)后的可選操作,不是在提交任務(wù)時(shí)選擇,可反復(fù)執(zhí)行。
在實(shí)踐中,當(dāng)數(shù)據(jù)遷移任務(wù)進(jìn)入同步狀態(tài)后,一般會(huì)先執(zhí)行一次數(shù)據(jù)校驗(yàn),再執(zhí)行相關(guān)的切庫(kù)切表操作。而對(duì)數(shù)據(jù)同步場(chǎng)景,一般會(huì)定期執(zhí)行全量數(shù)據(jù)校驗(yàn)。
數(shù)據(jù)訂閱
數(shù)據(jù)訂閱是將數(shù)據(jù)庫(kù)的數(shù)據(jù)變更實(shí)時(shí)拉取出來,并交付給下游應(yīng)用執(zhí)行相應(yīng)業(yè)務(wù)邏輯的過程。與數(shù)據(jù)遷移相比,數(shù)據(jù)訂閱邏輯較為簡(jiǎn)單——相當(dāng)于數(shù)據(jù)遷移中的增量過程,而在應(yīng)用場(chǎng)景方面,數(shù)據(jù)訂閱可以應(yīng)對(duì)更加多樣化的業(yè)務(wù)需求,例如:
- 通過數(shù)據(jù)訂閱維護(hù)全文索引一類的第三方索引庫(kù)
- 基于數(shù)據(jù)訂閱維護(hù)緩存
- 通過數(shù)據(jù)訂閱實(shí)現(xiàn)復(fù)雜業(yè)務(wù)異步解耦
- 實(shí)現(xiàn)更加復(fù)雜的ETL
數(shù)據(jù)訂閱的執(zhí)行邏輯如圖10所示。
圖10 數(shù)據(jù)訂閱執(zhí)行流程
數(shù)據(jù)訂閱任務(wù)由NDC的調(diào)度服務(wù)選擇合適的訂閱引擎節(jié)點(diǎn)執(zhí)行,與數(shù)據(jù)遷移增量過程不同的是,數(shù)據(jù)訂閱引擎不會(huì)將增量變更數(shù)據(jù)緩存在本地,而是直接丟入消息隊(duì)列中(使用了我們的消息隊(duì)列服務(wù)),SDK通過消費(fèi)消息隊(duì)列的數(shù)據(jù)實(shí)現(xiàn)增量數(shù)據(jù)回放。
之所以用消息隊(duì)列代替本地磁盤,是因?yàn)镾DK的數(shù)據(jù)回放過程完全由應(yīng)用方把持,速度不可控,若業(yè)務(wù)邏輯處理過慢,或下游節(jié)點(diǎn)意外宕機(jī),可能導(dǎo)致增量數(shù)據(jù)大量堆積,這里消息隊(duì)列可以當(dāng)做一個(gè)容量足夠大的消息緩存,使SDK端的異步消息回放更加優(yōu)雅。
數(shù)據(jù)訂閱中Engine必須嚴(yán)格按照增量數(shù)據(jù)的時(shí)間順序串行發(fā)布消息,無法做到類似數(shù)據(jù)遷移增量過程中的并發(fā)復(fù)制,這是因?yàn)橛嗛喨蝿?wù)Engine無法感知應(yīng)用端SDK消費(fèi)數(shù)據(jù),并發(fā)發(fā)布消息最終必然導(dǎo)致SDK消費(fèi)數(shù)據(jù)亂序執(zhí)行。
在實(shí)踐中,要特別注意消息隊(duì)列對(duì)發(fā)布消息的速率瓶頸以及訂閱任務(wù)Engine到消息隊(duì)列的網(wǎng)絡(luò)開銷。
關(guān)鍵特性
對(duì)NDC的實(shí)現(xiàn)部分,再分享三點(diǎn)關(guān)鍵特性給大家:
- 并發(fā)遷移
- 斷點(diǎn)續(xù)傳
- 多源適配
對(duì)數(shù)據(jù)遷移和同步,速度是生命線:如果遷移速度不夠快,任務(wù)永遠(yuǎn)無法進(jìn)入同步狀態(tài),遷移和同步也無從談起。NDC的全量和增量過程都支持并發(fā)遷移,保障遷移任務(wù)能夠盡快地進(jìn)入同步狀態(tài)。
全量遷移并發(fā)較為簡(jiǎn)單,首先可以在不同的表上做并發(fā)遷移,其次數(shù)據(jù)導(dǎo)入目標(biāo)端的過程也可以并發(fā)執(zhí)行,select數(shù)據(jù)和insert數(shù)據(jù)線程解耦在實(shí)踐中能夠極大縮短遷移時(shí)間,另外NDC的全量遷移可以配置一次導(dǎo)入操作的數(shù)據(jù)批量數(shù),減少遷移進(jìn)程和源端目標(biāo)端的交互次數(shù)。
增量并發(fā)回放是NDC最重要的核心實(shí)現(xiàn)之一,NDC增量回放線程會(huì)根據(jù)增量數(shù)據(jù)之間的沖突關(guān)系構(gòu)建一張或多張有向無環(huán)圖,圖中所有入度為0的數(shù)據(jù)節(jié)點(diǎn)都允許并發(fā)回放,增量數(shù)據(jù)導(dǎo)入目標(biāo)端后會(huì)從圖中刪除,從而解鎖其他沖突數(shù)據(jù)。這種算法理論上可最大限度發(fā)揮并發(fā)回放的優(yōu)勢(shì),在實(shí)際的性能測(cè)試中,NDC的增量并發(fā)回放效率遠(yuǎn)高于MySQL 5.7基于Group Commit的并行復(fù)制。
斷點(diǎn)續(xù)傳是NDC任務(wù)漂移和高可用實(shí)現(xiàn)的基礎(chǔ),是指遷移或訂閱任務(wù)異常退出,或進(jìn)程、節(jié)點(diǎn)crash之后,可以從最近的位置點(diǎn)重新啟動(dòng)任務(wù)。斷點(diǎn)續(xù)傳的實(shí)現(xiàn)有兩點(diǎn)前提:一是要求系統(tǒng)定期將任務(wù)的位置點(diǎn)信息持久化,在需要時(shí)可以從持久化過的位置點(diǎn)恢復(fù)任務(wù),NDC的做法是Engine定期將位置點(diǎn)信息上報(bào)給Center,由后者將其持久化在系統(tǒng)庫(kù);二是要求遷移和訂閱任務(wù)中所有數(shù)據(jù)導(dǎo)入操作(全量和增量)具有冪等性,對(duì)此我們可以采用具有replace語義的SQL實(shí)現(xiàn)導(dǎo)入操作,對(duì)不支持replace語法的目標(biāo)端,可以使用delete+insert的組合SQL實(shí)現(xiàn)類似語義。在實(shí)踐中,保障冪等操作絕對(duì)是一項(xiàng)省時(shí)省力省心的做法。
多源適配的問題主要在于對(duì)不同的源端數(shù)據(jù)庫(kù),采用怎樣的方式拉取增量數(shù)據(jù)最為實(shí)用和高效,目前主要有以下三種做法:
- 基于日志:MySQL binlog、Oracle redo log;
- 基于CDC:Oracle、DB2、SQLServer;
- 基于觸發(fā)器:適用所有支持觸發(fā)器的數(shù)據(jù)庫(kù)。
三種做法各有優(yōu)劣,觸發(fā)器用法較為簡(jiǎn)單,對(duì)用戶權(quán)限要求比較清晰,但性能較差,尤其是源端線上壓力比較大時(shí),可能產(chǎn)生大量的鎖超時(shí),因此不作為最優(yōu)選擇;CDC全名Change Data Capture,是一些數(shù)據(jù)庫(kù)特有的功能,可以將數(shù)據(jù)庫(kù)產(chǎn)生的增量數(shù)據(jù)同步到一些視圖或表中,遷移或訂閱進(jìn)程通過這些表和視圖來獲取增量數(shù)據(jù),可以看出CDC在使用上與觸發(fā)器非常類似,區(qū)別在于CDC是一些數(shù)據(jù)庫(kù)獨(dú)特功能,可以在性能上做優(yōu)化。以O(shè)racle為例,可以通過解析redo log產(chǎn)生增量數(shù)據(jù),比通過觸發(fā)器產(chǎn)生增量數(shù)據(jù)的做法對(duì)源端的影響要小很多,CDC的劣勢(shì)在于不同數(shù)據(jù)庫(kù)沒有統(tǒng)一規(guī)范,方言化嚴(yán)重,對(duì)權(quán)限要求更加苛刻。
一般情況下,我們將第一種基于日志的增量數(shù)據(jù)拉取方案列為最優(yōu)。以MySQL為例,MySQL自帶的binlog功能可以直接將日志同步到遠(yuǎn)端,對(duì)用戶權(quán)限、源端數(shù)據(jù)庫(kù)性能影響也都在可控范圍內(nèi)。
總結(jié)
工欲善其事,必先利其器,NDC顧名思義,就是希望為公司打造一個(gè)可以容納各種結(jié)構(gòu)化數(shù)據(jù)庫(kù)實(shí)時(shí)數(shù)據(jù)的“數(shù)據(jù)運(yùn)河”,并通過運(yùn)河將數(shù)據(jù)運(yùn)輸?shù)讲煌康亩耍瑧?yīng)用只需要在管理頁面中簡(jiǎn)單地配置幾個(gè)參數(shù),便可將數(shù)據(jù)庫(kù)的內(nèi)容輕松整合到其他數(shù)據(jù)或應(yīng)用系統(tǒng)中。
NDC的快速構(gòu)建,很大程度上要?dú)w功于我們團(tuán)隊(duì)在分布式中間件、數(shù)據(jù)遷移工具等領(lǐng)域的成果和積累,如果開發(fā)者要設(shè)計(jì)和實(shí)現(xiàn)類似系統(tǒng),建議多利用開源資源,比如調(diào)度模塊可以考慮集成或使用Apache Azkaban的實(shí)現(xiàn),任務(wù)執(zhí)行模塊也有很多開源工具和代碼可以參考。另外,在設(shè)計(jì)數(shù)據(jù)遷移和訂閱平臺(tái)時(shí)要重點(diǎn)考慮以下幾個(gè)問題:
與其他平臺(tái)集成,NDC具有平臺(tái)可插拔特性,可以非常方便地與網(wǎng)易其他平臺(tái)服務(wù)集成。
任務(wù)執(zhí)行要快,對(duì)源端影響盡可能小。NDC具有非常高效的數(shù)據(jù)全量遷移和增量數(shù)據(jù)回放模塊,在實(shí)現(xiàn)增量數(shù)據(jù)拉取模塊時(shí),盡可能選擇了同步日志的方式,對(duì)源端影響很小。
要考慮到斷點(diǎn)續(xù)傳問題。在任務(wù)執(zhí)行過程中,可能發(fā)生網(wǎng)絡(luò)抖動(dòng)、分區(qū)、節(jié)點(diǎn)故障等各類異常,這首先要求我們的任務(wù)具備從某個(gè)時(shí)間點(diǎn)或位置點(diǎn)重新開始執(zhí)行的能力,其次要求調(diào)度中心可以快速發(fā)現(xiàn)異常,并使用合理的算法實(shí)現(xiàn)任務(wù)漂移。
要考慮到灰度發(fā)布。由于NDC的平臺(tái)化設(shè)計(jì),隨著系統(tǒng)功能愈發(fā)繁多,一次平臺(tái)全面升級(jí)的代價(jià)越來越高,為此我們需要通過灰度升級(jí)保障功能在全面上線之前得到充分驗(yàn)證,另外通過功能“可插拔”的特性,保障一次上線對(duì)線上任務(wù)的影響盡可能小。
迄今為止,NDC上線半年多,承接應(yīng)用40+,遷移、同步和訂閱實(shí)踐案例10000+,可以預(yù)見,在網(wǎng)易未來的云計(jì)算、大數(shù)據(jù)布局,以及其他各類數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用場(chǎng)景中,NDC都將發(fā)揮舉足輕重的作用。