數據庫

DTCC2019 愛奇藝實時數據傳輸服務

廣告
廣告

數據庫間實時數據傳輸服務可簡化業務系統的數據架構,使其專注于業務開發。DBIO是愛奇藝研發的數據庫間實時數據傳輸服務,用于同異構數據庫間實時復制與數據變更捕獲,是業務系統數據共享的核心通道。

作者:郭磊濤

編輯:張曉藝

郭磊濤,愛奇藝數據庫服務負責人2007年博士畢業于中國科技大學,進入中國移動研究院負責大數據平臺的建設,2014年加入愛奇藝負責數據庫內核、中間件及運維系統的研發,熱衷于 Hadoop 生態系統優化和數據庫高效運維架構。

本文根據郭磊濤老師在DTCC數據庫大會分享內容整理而成,將介紹 DBIO 的設計與實現,重點分享在源和目標端故障時如何保證服務高可用、如何優雅的支持多種源與目標端系統以及如何高效運維等方案。同時,也將介紹 DBIO 在數據變更訂閱、異地多活、數據歸檔等方面的應用案例。

1. 愛奇藝數據庫架構

愛奇藝是一家以科技創新為驅動的偉大娛樂公司,科技創新的前提是提供穩定、安全、高性價比的基礎服務。數據庫服務團隊負責愛奇藝所有業務線的數據庫、數據庫中間件等的開發與運維工作。面對不同的業務角色,我們針對性地提供相應的服務。我們目前提供了基于開源和自研的緩存、kv、文檔、圖及關系數據庫,部署在物理機、虛機和公有云上,網絡環境異構、集群跨DC,這些都給數據庫運維帶來了巨大挑戰。

我們面向DBA的運維管理系統經歷了腳本、工具化、平臺化到智能化演變。運維平臺化可以確保規范運維,簡化運維操作,減少運維失誤。在此基礎之上,嘗試進行智能運維的探索。首先將常見故障及告警的根因定位封裝為工具,手動或自動觸發后對系統進行全面診斷。比如,MySQL主從復制延時告警可能是由寫入吞吐量過高、網絡故障、Slave節點IO/CPU打滿、大事務等因素引起,通過這些工具快速定位根因。另外,我們對報警也進行了多維度的聚合,從而減少不必要的告警或提高某些告警優先級等。同時,我們還對各數據庫集群進行容量管理,對不合理的資源進行動態縮容和擴容,并通過合理的數據庫實例分配和遷移策略,提升服務器利用率實現降低成本的目的。

對于應用的開發者,我們提供客戶端SDK及中間件,來實現運維操作對業務的透明,從而讓業務只關注業務邏輯的開發,而涉及到后端DB的工作則由SDK去處理,如連接超時和重試等機制。除了提高運維效率和開發效率外,自服務平臺提供詳細信息展示、預警報告、自助運維等功能,并結合智能客服來降低需人工處理的業務咨詢量。

本次將介紹數據庫服務團隊研發的數據傳輸中間件DBIO,它可以協助業務實現多端數據全量和實時同步。

2. DBIO簡介

DBIO是數據庫的數據遷移、實時變更訂閱與同步服務。它基于阿里開源的otter項目逐步完善而來,目標是成為數據庫間數據共享的通道,實現任意數據庫間數據的靈活搬遷與同步,讓業務只關注業務邏輯開發,而底層數據互通則通過DBIO來實現。

那么怎么實現數據的互通呢?首先,我們要解決的是如何高效的獲取源端數據庫的實時數據。各種數據庫,包括kv、文檔和關系數據庫在有數據變更時,比如插入、更新、刪除等都會記錄變更日志。這些變更日志一方面用于故障后重放以保證數據完整性,另一方面用于主庫和從庫之間的數據同步。那么,我們只需要獲取數據庫的變更日志,就可以得到實時的數據庫數據。 otter通過將其偽裝為MySQL的slave,獲取到mysql binlog,并經過ETL數據處理后寫入到目標系統。otter部署和使用時主要包括3個服務,即manager提供了web配置和同步任務控制接口,本身并不承擔數據同步的功能,真正的同步任務都運行在worker節點上,zookeeper用于記錄部分元數據及服務高可用的管理。

我們對otter做了擴展和優化,從而更匹配我們的業務需求,也更易于管理。比如,對源端數據庫的支持從MySQL擴展到5種數據庫,對目標端系統從MySQL擴展到11種,增加了內置向MySQL分庫分表同步的組件。支持了全量數據的同步、增強了HA和雙向同步、數據處理ETL各階段都支持用戶自定義插件從而實現更加靈活的數據條件過濾、類型/字段映射轉換以及寫入到目前端時數據存儲格式優化等等。本文將主要介紹我們對otter的功能增強的難點、實現方案及應用實踐。希望這些經驗可以幫助到大家了解如何基于otter來構建一個數據庫數據遷移與同步的服務,以及如何靈活的使用這個服務來滿足各種業務需求。

3. DBIO關鍵技術

3.1 源端支持更多的數據庫

在DBIO中除MySQL外,還支持TiDB、MongoDB、Redis、CB數據的實時獲取與同步。

1、TIDB

TiDB是PingCAP公司開源的分布式數據庫,適用于TP和AP的場景。在2017年下半年愛奇藝開始調研測試TiDB,并在2018年中正式上線,目前已經在視頻上傳、生產、風控等核心業務線應用。我們上線的業務大都是從MySQL遷移到TiDB的,MySQL上的數據變更訂閱、同步等也需要在TiDB上支持。同時,TiDB版本更新非常快,為了應對TiDB可能帶來的不穩定以及頻繁的升級等,我們需要把TiDB的數據同步到MySQL等其它系統。因此,我們在DBIO的源端也增加了TiDB。

TiDB的binlog是由TiDB Server生成并發送至Pump Cluster進行局部排序,之后再由Drainer模塊歸并排序最終形成全局有序的binlog日志,并同步到下游下游支持TiDB、MySQL等,同時為了方便接入其它系統,也支持Kafka。DBIO正是通過Kafka取到TiDB binlog,消費Kfaka消息,解析并轉換成DBIO的中間數據格式。我們在接入時主要遇到一些數據格式、數據類型等轉換的問題。由于TiDB binlog需要經過Pump cluster->Drainer->Kafka等幾個流程才可以得到,因此以TiDB為源的同步延時相對要高一些,實測在4-8秒。

2、其他

對于接入Redis和Couchbase(后簡稱cb)作為源端,我們采用和接入MySQL類似的方式,即DBIO偽裝成Redis和cb的Slave節點,來獲取全量和增量的數據變更。接入Redis時,我們啟動一個同步控制器Replicator,向Redis Slave發送PSYNC runid offset指令,Redis會根據runid和offset來判斷是否需要先做全量數據同步,如果需要的話會執行bgsave把內存中的數據存成rdb文件回傳。如果不需要,就從復制緩沖區backlog中直接取操作指令給DBIO。要注意的是,全量和增量數據格式不一樣,需要分別處理。

Couchbase是一個分布式NoSQL數據庫,一般作為緩存使用(后簡稱cb)。cb的kv讀寫性能高于redis,且擴展性非常好,所以在愛奇藝的幾乎所有在線業務都在使用cb。我們在DBIO中接入cb的主要動機是希望把cb數據轉存到其它更便宜的kv存儲中。因為cb數據要基于全內存存儲才可以達到很高的性能,成本較高。而我們發現有些業務雖然使用cb,但它們實際的qps和延遲要求并不高。這時,我們會建議它們遷移到同樣高性能但成本更低的基于ssd和內存的kv存儲上,這個kv存儲在我們內部的項目叫HiKV。HiKV是基于wisckey的存儲方式,即key和value分開存儲,key在內存,value在ssd,優化了LSM-Tree的寫放大問題。把cb接入到DBIO源端相比其它幾個系統要簡單一些,因為cb的數據復制協議DCP可以把cb變更,包括從磁盤上的存量數據以及內存中的數據寫入到DCP queue隊列中。我們只需要啟動一個DCP Client來讀取queue中的數據,解析即可。DCP Client讀數據時,會帶上起止序列號seqno,已經消費的序列號會記錄在zookeeper中。如果DCP client故障,DBIO failover到另外一臺服務器再從zookeeper讀取seqno就可以繼續從cb獲取數據了。

類似的方式,也可以得到mongodb的操作日志oplog,詳細的做法就不贅述了。

3.2 支持更多目標端系統

除了接入更多的源端外,我們對同步的目標端也做了擴展。

DBIO在讀取到數據并轉換為中間數據格式后,會通過ETL流程對數據進行過濾、轉換等。如果要接入更多目標端,只需要擴容Load模塊即可。Load模塊會根據配置來判斷目標是不是MySQL或TiDB,如果是MySQL或TiDB,會繼續判斷是否向分庫分表同步等等。如果目標端不是MySQL/TiDB,則會進入初始化異構目標端Loader的過程,這個過程會建立與目標端的連接,并將數據批量的寫入。在修改Load模塊時,我們遇到的問題主要是不同目標端數據格式不同的問題、每種系統寫入成功與否的確認方式、異常處理以及如何保證冪等。對于批量Load失敗時,DBIO會回落到逐條Load,以保證數據寫入成功。如果重試多次都寫入失敗,則該批次同步失敗,再次進行重試。

目標端分成兩個大的通道,其一是原生支持的MySQL,相對來說會比較成熟一些。我們拿到一條數據之后,來看它目標端是不是MySQL,如果是,就走MySQL通道,如果不是,就走異構的數據同步通道。如果是像MySQL同步,我們會看目標端是不是分庫分表,如果是分庫分表,會有一個組件來自動將其同步至分庫分表。如果是向異構數據同步,我們會先做批量,如果是批量有失敗,再逐條加載。

在接入多種目標端時,也支持向MySQL分庫分表的同步。目標端是分庫分表的場景在愛奇藝非常常見。比如在業務上線初期并未預想到數據的增量,上線一段時間后發現只有分庫分表才能滿足需求。通過DBIO可以幫業務提前把全量和增量數據同步至分庫。在接入分庫分表時我們也走了一些彎路,最初為了接入方便,我們直接用mysql proxy實現分庫分表,DBIO寫proxy。但是因為引入了proxy,同步出現錯誤或延時,問題排查比較復雜,而且proxy為了實現高可用還需要引入虛擬ip或域名,這又增加了一層依賴。隨后,我們拋棄了proxy這種外接的分庫分表中間件,而是把這個功能緊耦合進DBIO的Load模塊,通過groovy配置分庫分表規則,在性能、靈活性和運維復雜性上都有降低。

Load模塊中內置的分庫分表組件的實現:Load模塊會初始化分庫分表規則,并把路由規則緩存在內存。對于每一條數據,都通過路由規則計算,得到它在目標端的實際數據庫名和表名,并把這個信息回填到該行記錄中。這里要特別提出的是,如果shardingkey(分片鍵)上有update操作,Load模塊會提前把update分解為2個操作,即delete+insert。修改完記錄后,把該行記錄發送到并行加載通道。并行加載通道中,首先對同一個主鍵上的I/U/D操作進行合并,比如U+D合并為D,I+U合并為I等,目的是減小寫入目標端的記錄數。之后根據DML類型排序,再去構建對應的SQL語句。SQL語句執行的粒度是,每個PrepareStatment會并行執行,執行之前會查詢該SQL語句的目標端,獲取分庫datasource后寫入。 在分庫分表組件中,我們把原來的DBCP連接池替換為更為高效的HikariCP,吞吐量有了15%的提升。與外接Proxy的方案相比,內置分庫分表組件的吞吐量提升60%。另外,我們對不同分庫分表數也做了壓測,分庫分表數越多,性能越低。因此,需要合理設置分表,并不是越多越好。

3.3 MySQL全量數據同步

進行全量的數據在DB間搬遷,需要考慮的最主要問題就是限流,即如何讀源端數據避免影響源端正常的讀寫,如何寫目標端系統避免寫入QPS過高導致數據積壓或復制延遲等。另外需要考慮的就是如何控制數據遷移的整體邏輯,比如如何并發讀寫,如何進行錯誤重試等。

將MySQL數據全量導出到其它系統的方案,包含2個模塊,即數據提取模塊extract task和數據導入模塊load task。通過流程控制器來協調兩個模塊的工作,并對異常信息同步進行重試和記錄。在流量控制方面,采用從mysql流式讀取的數據,并且通過令牌桶來保證讀取數據的QPS在設置的范圍內。之后,對讀到的數據進行業務自定義的過濾和轉換,并寫入到一個BlockingQueue中。Load任務從BlockingQUeue讀數據,并批量或單條寫入目標端。如果目標端負載較高,寫入QPS低,則BlockingQueue有數據積壓,Extract任務也會阻塞,直至目標端正常。通過讀寫限流,避免了全量同步對源和目標端的影響。

3.4 DBIO HA方案

DBIO一般應用于實時在線的數據同步,所以需要保證在各種故障下可以快速檢測故障并恢復,保證同步流程的正常運維。那么可能造成同步異常的故障有哪些呢?分別為:源端DB異常、目標端系統異常以及DBIO服務進程異常。

首先,介紹一下數據庫系統本身的高可用方案。以MySQL 的一主多從集群中主庫故障為例,來看MySQL本身如何實現failover。我們在每臺服務器上都會啟動一個agent進程,它會監控在這臺服務器上的多個mysql實例的狀態,并與master集群保持心跳。某個MySQL主庫故障時,agent會監控到該信息,Master集群中的leader節點會對這個mysql集群進行多路檢測,以確認該mysql主庫確實故障,之后會選擇出合適的從庫來提升為主庫。新主庫的選擇策略是,與原master同機房,且具有最新的binlog和relaylog。一旦某個從庫提升為主庫,其它從庫都需要從新主庫apply差異的binlog,之后master會將原故障主庫上的域名重新綁定到新MySQL 主庫上并更新CMDB的信息,完成MySQL failover過程。為了避免HA Master的單點故障,我們啟動了多個HA Master組成raft group來實現HA Master的高可用。

現在看DBIO如何應對源端系統的failover。源端系統failover期間,DBIO肯定會觸發連接異常,經過多倫重試仍失敗時,則從CMDB查詢到最新的主庫,并根據之前同步的最新時間點,找到從新主庫上同步的起始位置后開始同步。如果開啟了gtid,則根據gtid來確定從新主庫同步的起始位點。

對于目標端故障,我們也是類似的方案。區別是,源端是通過DB的IP和端口來獲取數據,目標端通過域名訪問數據庫。數據庫團隊發布的SDK,對數據庫failover的異常處理做了封裝。所以,目標端的failover在DBIO這端基本不需要做什么。

那么,DBIO本身如果故障,是怎么處理的呢?這個比較簡單,也是otter原生就支持的。它通過zookeeper來監控各個worker節點是否在線,如果有worker節點異常,manager會將dead worker上的同步流遷移到備用worker上。從線上數據庫和DBIO的failover耗時統計看,基本上故障在不到1分鐘內可以自動檢測并恢復正常。

3.5 MySQL間雙向同步方案

數據庫間雙向同步需要重點解決的是如何避免數據回環,即從A同步到B的數據,不能再從B同步回A,否則這個數據就會在兩個DB間相互不停的寫入。

我們的解決方案是,在通過DBIO寫入目標MySQL時,對同步的數據打上標記。然后在DBIO的Select讀數據時檢查這個標記,丟棄回環數據。如上圖示例,3個數據庫分別負責同一個業務不相交的數據寫入,但是通過DBIO來做相互同步,最終每個DB都存儲有全量數據。我們看從mysql2到mysql3的DBIO同步。對于3條記錄,第一條記錄是mysql2寫入的,DBIO未發現標記位,則同步到mysql3。第2條數,里面有標記且是mysql3的標記,與目標端相同,則丟棄。第3條數據,有標記但是mysql1的標記,不構成回環,則把數據寫入mysql3。應用雙向同步有一個前提條件,就是兩個雙向同步的DB上不能同一時間對同一個key更新,否則會造成沖突。這就要求業務在應用雙向同步時首先需要對數據進行單元化切分。

基于雙向同步,我們進一步可以實現MySQL的異地多活。類似于前面介紹的雙向同步的約束條件,我們可以把業務單元化數據部署到不同的地域(比如兩地三中心),通過DBIO雙向同步,從而每個DB都有完整的數據。另一方面,有一些全局數據無法拆分,可以仍然采用MySQL主從集群或Group Replication集群部署。如果某個Region故障,則可以把流量切到其它Region。數據庫服務團隊提供的SDK接入了配置中心,當切換到另外一個Region的集群時,修改配置中心的配置。SDK接收到配置變更通知,會逐步斷開老連接,并連接到新配置的集群。所以SDK在我們的應用開發中占有非常重要的作用。

4. DBIO自服務平臺

前面介紹了一些功能和方案,那么如何把這個工具變的易用也非常重要。我們開發了一個基于Web的自服務平臺,業務可以提交同步流申請、查看同步狀態、訂閱告警、并可對工作流進行啟停或配置修改等操作。如何把這些繁復的運維和告警處理自動化,就依賴后臺的工作流引擎。

當接收到一個運維工單或告警時,會把它和事先定義好的一個工作流任務關聯。這個工作流任務就是處理這個工單或告警的一系列腳本。工作流引擎生成工作流任務的配置信息,并提交執行任務。處理腳本提前保存在gitlab上,工作流任務執行引擎從gitlab下載腳本,并根據工作流的順序來執行這些腳本。

上圖示例的是DBIO服務部署工作流,在執行時會讀取工單信息和CMDB信息,生成同步任務的配置,并選擇同步任務的執行集群和worker節點,配置生成后就可以啟動同步任務了。為了保證服務的高可用,DBIO的集群是跨IDC部署的,這樣單個IDC故障,不影響可用性。在進行同步流任務調度時,根據worker節點的資源利用率以及與原和目標端系統的延時來選擇合適的worker。

5. DBIO在愛奇藝的應用

DBIO已經在愛奇藝穩定運行2年多,有千條實時同步流,百萬行/秒的吞吐量,延時在500ms左右。各種目標端對比看,MySQL間的同步需求最多,主要用于DB功能拆分。另外MQ方面,之前主要是AMQ,但由于它擴展性及容錯性差,逐步被RocketMQ所替代。

DBIO常見應用場景

首先是用于模塊間的消息通知。在用DBIO之前,業務需要寫DB成功后再發送MQ,通知其它模塊。現在業務只需要直接寫MySQL,消息通知交由DBIO,同時MQ的消費端也可用于實時數據分析。

第二種場景是DB功能拆分。對于一個業務的基礎庫,由于需要支持多表事務,所以只能在一個MySQL中存儲所有數據。但是,這個業務的多個子系統可能只需要部分數據。如果這些子系統直接讀基礎庫,一方面可能會造成影響,另外一個方面也不方便自己擴展進行個性化的表定義。這種場景下,可以使用DBIO來做功能拆分,即每個子系統只同步需要的數據。這樣業務開發會更加靈活。

另外一個場景就是多庫映射到一個庫上,比如多表合并成一個寬表、將多個庫中的表匯總到一個庫以及實時歸檔等。

當然,還有M到N的同步映射,一般應用于分庫分表改變了映射規則、分庫擴容或數據遷移等場景。

還有一種應用場景是在分表上實時構建反向索引。比如業務希望基于用戶查詢對應的紅包信息,也需要根據紅包查詢用戶信息。此時業務可以只寫用戶表(基于用戶id分表),DBIO讀取用戶表變更信息,并把數據重新寫入到紅包表(基于紅包id分表)中。

6. 展望

雖然DBIO已經比較穩定,但一些問題還沒有完全或優雅地解決。比如源端DDL操作如何優雅的同步到目標端,如何高效地校驗同步數據的一致性等。同時,我們也正在把業務常見的使用方案進行封裝,變成通用易用的平臺能力,更好地為各業務線服務。

我的分享就到這里,謝謝大家!

我還沒有學會寫個人說明!

浪商FP5466G2服務器評測

上一篇

5分鐘帶你了解浪潮商用機器FP5466G2服務器

下一篇

你也可能喜歡

DTCC2019 愛奇藝實時數據傳輸服務

長按儲存圖像,分享給朋友

ITPUB 每周精要將以郵件的形式發放至您的郵箱


微信掃一掃

微信掃一掃
双色球常规走势图 最赚钱的汽车厂家 飞禽走兽多人版鲨鱼压法 二中二公式表 极速飞艇首页 内蒙古快3开奖号码 时时彩后三杀一码不挂方法 网易棋牌游戏官网 重庆时时彩龙虎走势图 投资小赚钱快的微商产品项目 2978棋牌游戏中心官网 章鱼直播 排列三走势图