一、前言 在攜程國際化戰略背景下,海外業務將成為新的發力點,為了保證用戶高品質的服務體驗,底層數據勢必需要就近服務業務應用。一套標準且普適的數據複製解決方案能夠提升業務決策效率,助力業務更快地觸達目標用戶。 DRC (Data Replicate Center) 作為攜程內部資料庫上雲標準解決方案, ...
一、前言
在攜程國際化戰略背景下,海外業務將成為新的發力點,為了保證用戶高品質的服務體驗,底層數據勢必需要就近服務業務應用。一套標準且普適的數據複製解決方案能夠提升業務決策效率,助力業務更快地觸達目標用戶。
DRC (Data Replicate Center) 作為攜程內部資料庫上雲標準解決方案,支撐了包括但不限於即時通訊、用戶賬號、IBU在內的核心基礎服務和國際業務順利上雲。
二、業務上雲場景
業務上雲前,要先要思考2個問題:
-
資料庫是否需要上雲?
-
在資料庫上雲情況下,海外資料庫提供只讀還是讀寫操作?
1、應用上雲
針對用戶延遲不敏感或者離線業務,可以採用只應用上雲資料庫不上雲,請求回源國內。該方案下業務需要改造應用中讀寫資料庫操作,根據應用部署地,決定流量是否需要轉發。
不建議海外應用直連國內資料庫,網路層面專線距離遠,成本太高,不現實;安全層面應禁止跨海訪問,否則可能導致預期就近訪問流量由於非預期錯誤,將海外流量寫入國內資料庫,從而引起國內數據錯誤。
2、資料庫上雲
對於線上用戶延遲敏感應用,資料庫必須跟隨應用一同上雲,將請求閉環在海外,從而就近提供服務響應。在確定資料庫上雲的前提下,根據不同業務特點,可再細分為海外只讀和讀寫兩種場景。
1)只讀場景
對於海外只讀場景,國內數據只需要單向複製,該方案下業務海外賬號預設無寫許可權或者業務改造寫操作,避免出現由於誤寫導致國內海外數據不一致。
2)讀寫場景
對於海外讀寫場景,國內海外數據需要雙向複製,業務代碼無需改造。該方案下由於有2個Master可以寫入,業務需要在應用層對流量進行切分,比如用戶歸屬地維度,從而避免在兩側同時修改同一條數據,進而導致複製過程出現數據衝突。
3、上雲成本
數據距離用戶越近,應用直接提供的服務功能越豐富,對應業務改造量越小,機器資源消耗量越大。攜程海外應用部署在AWS公有雲上,AWS入口流量不計費,只針對出口流量計費。應用上雲資料庫不上雲場景,請求回源國內產生出口流量費用;只讀業務單方向數據複製流入,不收費;讀寫業務數據複製回國內產生出口流量費用。
上雲成本主要集中在流量和資料庫費用。AWS出口Internet流量0.09$/GB,當流量大時,可通過數據壓縮,損耗複製延遲降低出口流量;RDS根據核數計費,1004元/核/月,業務流量少時採用普通4C16G機型即可,流量增加後動態提升配置。核心業務RDS配置一主一從,非核心業務單主即可,並且多個DB可共用一個集群,進而降低成本。
4、小結
為了提供高品質的用戶體驗,數據勢必需要上雲。在解決了是否上雲的問題後,如何上雲就成為新的疑問點。下麵就詳細分析攜程內部上雲過程中依賴的資料庫複製組件DRC實現細節。
三、資料庫上雲方案
DRC基於開源模式開發,公司內部生產版本和開源保持一致,開源地址:https://github.com/ctripcorp/drc,歡迎關註。
DRC孵化於異地多活項目,解決國內異地機房間資料庫同步問題。當其中一個或多個機房位置轉變為公有雲時,伴隨著物理距離的擴大,新的問題應運而生。
就DRC自身架構實現而言:
-
公有雲和國內機房間互不聯通,同步鏈路被物理阻斷;
-
公網傳輸不如國內跨機房之間專線質量,丟包頻發;
-
公有雲資料庫自主運維靈活性下降,如無法獲取root許可權,直接導致set gtid_next無法正常工作。
就業務接入而言:
-
國內海外數據隔離,按需複製成為剛需;
-
公有雲資料庫成本壓力導致混部,一對一複製不再滿足業務靈活多變的真實部署場景。
基於以上限制,DRC調整架構,引入代理模塊解決網路聯通性問題,借用事務表降低複製鏈路對許可權的要求;為了適應業務的多樣性,分別從庫、表和行維度支持按需複製。
1、架構改造挑戰
1)架構升級
DRC中有2個核心功能需要跨公網傳輸數據:
-
業務Binlog數據複製
-
DRC內部延遲監控探針
① 數據複製
以單向複製為例,在Binlog拉取模塊Replicator和解析應用模塊Applier之間引入Proxy,負責在TCP層將內網/公網流量轉發到公網/內網。Proxy綁定公網IP,採用TLS協議加密傳輸內網流量。鑒於公網質量不穩定特性,Proxy使用BBR擁塞控制演算法,優化丟包引起的卡頓。
Proxy作為公網數據傳輸攜程內部統一的解決方案,開源地址:https://github.com/ctripcorp/x-pipe,歡迎關註。
② 延遲監控
延遲監控探針從業務流量同側機房的Console寫入到業務資料庫延遲監控表(初始化時新建),經過雙向複製鏈路,從異側機房接收延遲探針,從而計算差值得到複製延遲。為了提升Proxy間隔離性,數據複製和延遲監控可以分別配置不同的Proxy實例實現數據傳輸。
③ Proxy Client
由於Applier和Console都需要對接Proxy,如何降低Proxy對DRC系統的侵入性就成為一個需要解決的問題。為此我們藉助Java Agent技術,動態修改位元組碼,實現了可插拔的接入方式。接入方只需要引入proxy-client獨立Jar包,業務層按需實現Proxy的註冊和註銷。
2)網路優化
公網網路丟包和擁塞頻發,為了在弱網環境下實現平穩複製,就需要快速地異常檢測恢復機制。除了在系統層將Proxy擁塞控制演算法優化為BBR外,DRC在應用層額外增加:
-
心跳檢測,實現連接自動切換
-
流量控制,避免突增流量引起資源耗盡進而影響數據複製
-
2條互備海外出口運營商線路,隨機切換
① 心跳檢測
Binlog生產方Replicator定時對下游消費方進行心跳檢測,消費方接收到心跳檢測需回覆響應,Replicator根據最後一次接收時間檢測並自動關閉長期沒有響應的連接。
這裡有一種場景需要特別處理,當下游消費方比較忙,主動關閉連接auto_read屬性時,由於應用層無法讀取暫存在緩衝區的心跳包,從而造成無法響應。這就需要消費方在auto_read改變時,主動上報生產方自身的auto_read狀態。
② 流量控制
公網網路質量下降導致複製延遲變大,數據堆積在發送端Proxy,進而引起Replicator和Proxy觸發流控;MySQL性能抖動,應用Binlog速度減緩,數據堆積在Applier,進而引起Applier觸發流控並逐層反饋到Replicator。
③ 運營商線路
針對Proxy出口IP,分別配置移動和聯通兩條運營商線路,當Binlog消費方由於觸發空閑檢測出現超時重連時,Proxy會隨機選擇一個運營商出口IP,從而實現運營商線路的互備。
3)事務表複製
國內機房間數據複製時,DBA可以給予DRC擁有root許可權的賬號,以實現Applier模擬原生Slave節點set gtid_next工作方式應用Binlog,從而將一個事務變更從源機房複製到目標機房,並且在兩端分配到同一個gtid下。但是公有雲上RDS出於安全原因是無法開放root許可權,直接從原理上否定了原有的複製方案。
為了找到合理的替換方案,我們首先從MySQL服務端視角分析下set gtid_next的效果:
-
事務在提交後會被分配指定的gtid值,否則MySQL服務端會自動分配一個gtid值;
-
gtid值加入MySQL服務端全局變數gtid_executed中。
其根本性作用在於將DRC指定的gtid值保存到MySQL系統變數。既然無法利用MySQL系統變數,那麼從業務層增加一個複製變數保存gtid信息即可實現同等效果。
其次,轉換到DRC複製視角,set gtid_next起到如下作用:
-
記錄Applier複製消費位點,並以此向Replicator請求Binlog;
-
解決迴圈複製,Replicator根據gtid_event中的uuid判斷是否是DRC複製產生的事件。
綜上分析,新的替代方案需要引入持久化變數,記錄複製位點並且能夠提供迴圈阻斷信息功效,為此DRC引入基於事務表的同步方案解決了海外複製難題。
① 位點記錄
海外複製業務集群需要新增複製庫drcmonitordb,其中新建事務表gtid_executed。
CREATE TABLE `drcmonitordb`.`gtid_executed` (
`id` int(11) NOT NULL,
`server_uuid` char(36) NOT NULL,
`gno` bigint(20) NOT NULL,
`gtidset` longtext,
PRIMARY KEY (`id`,`server_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
server_uuid:源端資料庫UUID號。
-
gno:事務id。該列值為0的行為彙總行。
-
gtidset:對於gno=0的彙總行,該列批量存儲gno編號,例如server_uuid:1-10:20:30。
當Applier應用SQL到目標資料庫前,需要先更新事務表,記錄gtid,然後再執行事務中變更語句,完整的複製流程如下圖所示。事務表中gno=0行中gtidset等效MySQL系統變數gtid_executed,Applier執行過程中定時彙總非0行事務gno,從而達到記錄位點功能。
② 迴圈阻斷
針對Binlog中第一個寫事件是事務表gtid_executed操作的事務,Replicator將其判斷為DRC複製數據,從而阻斷迴圈複製,否則一條數據會在雙向複製環內無限死迴圈。
2、業務落地挑戰
至此DRC解決了理論上阻礙複製的已知技術問題,在實際業務落地過程中,出於數據安全、費用和改造成本的考慮,業務對數據複製提出了更精細化控制的需求。
1)數據隔離
出於合規的要求,業務上雲後,需要完成國內和海外用戶數據的隔離。業務上雲前,國內和海外用戶數據全部在國內資料庫;上雲時就需要將海外用戶數據單獨複製到公有雲而過濾掉國內用戶數據。
① 庫表映射
上雲前國內和海外數據在同一張母表。為了上雲,業務通過在國內資料庫新增子表,實現國內數據的分離。海外由於只存在海外數據,所以物理上只需要一張母表即可,即國內子表與海外母表相對應,搭建DRC實現雙向複製即可。由於母表和子表表名不同,複製時需要做庫表映射,從而屏蔽應用層對不同表名的感知,降低業務改造量。
② 行過濾
庫表映射不涉及數據過濾,經過DRC的流量都會進行複製,因此映射在Applier端處理,直接根據映射規則替換表名即可。為此業務需要進行2處改造:
-
人工分離國內機房國內和海外數據;
-
為了使國內母表保存全量數據,海外用戶數據經過DRC複製回國內時,需要通過觸發器自動同步到母表。
為了進一步降低業務改造量,DRC提供行過濾功能,用戶無需進行業務改造,只需保證表中包含Uid欄位即可,DRC根據Uid自動判斷數據歸屬地,進行數據過濾。
單向複製鏈路級別添加行過濾配置,其中包括:
-
過濾類型
(a)Uid過濾,業務層面一般通過Uid維度進行拆分,通過SPI動態載入Uid過濾實現,攜程內部由於Uid無特殊標記,無法通過Uid名稱判斷出歸屬地,只能通過SOA遠程調用實時判斷Uid歸屬地獲得過濾結果;如果Uid有規則可循,則可以通過正則表達式匹配即可。
(b)Java正則表達式,支持針對單欄位的Java正則表達式簡單匹配計算,適合單一維度數值有規則的業務場景。
(c)Aviator表達式,支持針對多欄位的Aviator表達式複雜匹配計算,適合多維度數值相關聯的業務場景。
-
過濾參數
包含表到過濾欄位的映射關係,以及與過濾類型對應的上下文,比如正則表達式。
Applier Binlog請求中攜帶行過濾配置,Replicator根據過濾類型載入對應的過濾規則,從而計算出過濾結果。
行過濾在發送端Replicator實現,這樣實現的好處是跨海發送數據量大大降低,但同時也帶來瞭解析和重構Rows Event的複雜性和性能損耗,即先解析Rows Event並根據過濾後的行數據生成新的Rows Event。Rows Event的解析需要表結構信息,而表結構信息是保存在Binlog的頭中,勢必在Rows Event前保證能夠獲得對應的表結構;解析後就可以將每行過濾欄位值應用到過濾規則上,若匹配出需要過濾的行,則需要根據過濾後的行構造新的Rows Event併發送,否則直接發送即可。
2)資料庫混部
核心業務隨著數據量的膨脹,會採用分庫來降低資料庫壓力,在公有雲部署時,鑒於雲上初始流量不多,並且可動態提升機器配置,DBA部署時會將所有分庫部署在同一個RDS集群,此時複製從一對一變成一對多。
① 表過濾
單向複製鏈路級別添加庫表過濾配置,支持Aviator表達式。Replicator發送前,通過將從Binlog中解析的庫表名作用於Aviator表達式從而得到過濾結果。
3、資料庫上雲流程
完整的業務上雲流程一般分為四步:
-
資料庫先上雲,搭建國內海外資料庫複製,驗證海外數據可用性和完整性;
-
在海外數據可用的前提下,應用上雲,就近訪問海外資料庫,驗證部署海外應用可行性;
-
流量路由層灰度業務流量,可根據Uid白名單、流量百分比在流量接入層進行灰度,驗證業務邏輯正確性;
-
灰度完成,國內和海外流量完成切分,驗證國內和海外業務隔離性,為此後下線底層數據複製做準備。
資料庫上雲在每一步都有所涉及,第一步通過DRC解決了數據的可用性問題,第二步通過資料庫訪問中間件解決了數據可達性問題,第三步業務通過流量準確切分保證數據一致性問題,第四步國內海外實現數據隔離後,即可下線DRC數據複製。在分析完DRC原理後,下麵再分析下其他幾步資料庫相關問題。
1)數據訪問層
Dal包含中心化配置管理服務端Dal Cluster和Dal客戶端兩部分。上雲前同一個資料庫物理上只有一個集群,上雲後海外增加相同集群,服務端Dal Cluster就需要根據客戶端環境下發正確的MySQL配置文件。
① Dal Cluster原理
Dal Cluster變更推送功能藉由分散式配置中心完成,配置中心提供子環境功能,國內資料庫配置預設放在父環境,海外資料庫則會在上線流程中生成對應的子環境資料庫配置。這樣在Dal Client啟動時,帶有不同環境配置的客戶端會拉取到不同的配置,從而實現資料庫的就近訪問,整個過程對業務透明,代碼無需改造。
2)流量切分
業務上雲一般採用Uid歸屬地進行流量切分,當流量開始灰度後,兩端資料庫都開始接收寫流量。如果流量灰度不幹凈,針對同一個Uid數據在兩端同時被修改,則會導致底層DRC數據複製時出現數據衝突。
當衝突發生時,Applier預設根據時間戳進行衝突策處理,接入DRC的表都有一個精確到毫秒自動更新的時間戳,時間戳最新的數據會被採用,從而實現數據的一致。
3)表結構變更
通過DRC複製的集群,在表結構變更流程中,會自動關聯到公有雲集群,在兩端同時進行變更操作。
由於變更完成時間有先後,假設一個增加欄位的變更海外先完成,在國內完成變更前的時間範圍內,針對該表海外到國內的複製將出現複製衝突,預設DRC會捕獲該異常,並從異常信息中提取出列名,將多出的列從SQL中移除後再執行,從而自動處理掉衝突。
當國內集群完成表結構變更後,新增列的值在兩端都為預設值,數據仍然一致。
4、業務落地成果
1)海外資料庫複製從2021年11月上線至今,接入公司90+複製集群;
2)上海↔新加坡AWS複製平均延遲90ms,上海↔法蘭克福AWS複製平均延遲260ms;
3)賬號集群通過庫表映射,常旅、收藏等通過行過濾實現用戶數據隔離;
4)通過一對多部署,公有雲/國內機房MySQL集群比維持在1/5,DRC複製成本/MySQL集群成本維持在2/5。
四、未來規劃
1)為了支持更多Binlog消費方,支持消息投遞;
2)DRC當前只支持增量數據的實時複製,後續會支持存量數據的複製以及敏感數據的初始化過濾,覆蓋業務上雲過程中更多數據複製場景;
3)Replicator作為有狀態實例,使用本地磁碟保存Binlog,公有雲使用的塊存儲本身即是分散式存儲系統,Replicator可探究存儲架構改造,實現主備共用同一份存儲,從而降低使用成本。
DRC開源地址:https://github.com/ctripcorp/drc
本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/How-does-Ctrip-Overseas-MySQL-achieve-millisecond-level-data-replication.html