[張玉康]
為了保護用戶隱私和商業(yè)機密,國家交通運輸部在2017 年1 月發(fā)布了《網(wǎng)絡(luò)預約出租汽車運營服務(wù)規(guī)范》,其中規(guī)定了加密乘客電話號碼等安全措施。為滿足這個要求中間號應(yīng)運而生。中間號產(chǎn)品通過提供臨時聯(lián)系中間號,可以幫助隱藏服務(wù)雙方真實號碼,保護用戶隱私和商業(yè)機密,提供更加安全和可靠的通信服務(wù)。隨著時間的推移,中間號產(chǎn)品不斷發(fā)展壯大,已經(jīng)覆蓋了即時配送、電商、快遞、出行等多個行業(yè),每日呼叫量達到了千萬級別。業(yè)務(wù)的飛速發(fā)展給系統(tǒng)數(shù)據(jù)庫的高可用性和穩(wěn)定性帶來了挑戰(zhàn)。因此,如何設(shè)計高可靠且簡單的后臺服務(wù)器架構(gòu),是系統(tǒng)穩(wěn)定發(fā)展的必要條件,具有非常重要的研究意義和實踐價值。
傳統(tǒng)的數(shù)據(jù)庫備份只能在同一機房內(nèi)進行數(shù)據(jù)復制,所有數(shù)據(jù)都運行在同一機房內(nèi),因此可用性得不到確切的保障,同時無法滿足異地服務(wù)的快速訪問,降低了用戶體驗。一旦一個機房發(fā)生故障,所有數(shù)據(jù)將無法使用,整個中間號業(yè)務(wù)都會受到影響,可用性極差。高可用性(HA)是系統(tǒng)設(shè)計的重要指標之一,指標是指降低系統(tǒng)不能提供服務(wù)的時間,即不間斷地提供服務(wù)。高可用的數(shù)據(jù)庫設(shè)計是提升可用性的重要手段。
異地多活架構(gòu)有3 種模式,分別是存儲通用型異地多活、業(yè)務(wù)通用型異地多活和業(yè)務(wù)定制型異地多活。其中,業(yè)務(wù)通用型異地多活和存儲通用型異地多活適用于大型公司的業(yè)務(wù),設(shè)計和開發(fā)成本較大。業(yè)務(wù)定制化異地多活適用于中小型公司,設(shè)計和開發(fā)成本較小,所以本文采用業(yè)務(wù)定制化異地多活的模式。
本文介紹了一種基于Canal 實現(xiàn)數(shù)據(jù)庫雙活的架構(gòu)[1~8],該架構(gòu)以MySQL 數(shù)據(jù)庫為源數(shù)據(jù),模擬了MySQL 自帶的同步復制功能。它通過讀取MySQL 的BINLOG 日志,將BINLOG 發(fā)送到目的IP,然后使用adapter 程序在目的機器上解析并將數(shù)據(jù)備份入庫。相比原生的數(shù)據(jù)庫同步架構(gòu),該架構(gòu)具有更高的實時性,并且可以接入監(jiān)控平臺查看數(shù)據(jù)同步進度的情況?;贑anal 實現(xiàn)數(shù)據(jù)庫雙活的架構(gòu)可以提高數(shù)據(jù)庫備份和恢復的效率和性能,保證系統(tǒng)的高可用性和可靠性。同時,該架構(gòu)還具有很好的擴展性和定制性,可以根據(jù)不同的業(yè)務(wù)需求進行靈活的配置和調(diào)整。
異地雙活架構(gòu)本質(zhì)上是CAP 理論的CP 方案[9~12],是為了解決分布式一致性問題而設(shè)計的。CAP 理論關(guān)注的粒度是數(shù)據(jù)而不是系統(tǒng),并且需要根據(jù)不同業(yè)務(wù)的數(shù)據(jù)特點來設(shè)計異地多活。雙活的目的是為了在發(fā)生災(zāi)難時,能夠快速切換到備份系統(tǒng),保證業(yè)務(wù)的正常運行。然而,雙活并不是一種萬能的解決方案,它也有自己的局限性和挑戰(zhàn)。本節(jié)將從3 個方面分析雙活的設(shè)計原則,以及它們對業(yè)務(wù)的影響。
(1)只保證核心業(yè)務(wù)[13]。由于不同業(yè)務(wù)的數(shù)據(jù)特點不同,無法做到所有數(shù)據(jù)同步。例如,一些業(yè)務(wù)的數(shù)據(jù)量很大,復制成本很高;一些業(yè)務(wù)的數(shù)據(jù)變化很頻繁,復制延遲很高;一些業(yè)務(wù)的數(shù)據(jù)依賴很強,復制邏輯很復雜。因此,需要根據(jù)業(yè)務(wù)的重要性和敏感性,選擇合適的雙活策略。對于核心業(yè)務(wù),可以采用雙向復制或主備復制,保證數(shù)據(jù)的高可用和高一致性;對于非核心業(yè)務(wù),可以采用單向復制或異步復制,降低數(shù)據(jù)的可用性和一致性要求。
(2)只能做到最終一致性[14]。復制過程肯定會有時間延遲,因此需要拋棄一致性幻想。在設(shè)計雙活架構(gòu)時,我們需要拋棄一致性幻想,只能做到最終一致性。這意味著,在不同節(jié)點上的數(shù)據(jù)可能會在一定時間內(nèi)出現(xiàn)不一致的情況,但最終會趨于一致[13]。在實際應(yīng)用中,可以通過設(shè)置合理的時間窗口和沖突解決策略來降低數(shù)據(jù)不一致的概率。例如,可以采用樂觀鎖或悲觀鎖等方式來控制并發(fā)訪問,以減少數(shù)據(jù)沖突的可能性。此外,還可以采用一些分布式一致性協(xié)議,如PAXOS、Raft 等,來保證數(shù)據(jù)的一致性。
(3)只能保證絕大部分用戶[13]。不要為了0.01%的用戶,而影響了99.9%的用戶。在設(shè)計雙活架構(gòu)時,我們需要權(quán)衡不同用戶的需求和系統(tǒng)的可用性。不能為了小部分用戶而影響到絕大部分用戶的使用體驗。因此,需要在設(shè)計時考慮用戶的分布情況和系統(tǒng)的可擴展性,以確保系統(tǒng)能夠支持更多的用戶和業(yè)務(wù)需求。例如,可以采用負載均衡和自動擴容等方式來提高系統(tǒng)的可擴展性和容錯性。同時,還需要針對不同用戶和業(yè)務(wù)需求,采取不同的容錯和恢復策略,以保證系統(tǒng)的高可用性和數(shù)據(jù)的安全性。
綜上所述,異地雙活是一種權(quán)衡和妥協(xié)的方案[15,16],它既要保證業(yè)務(wù)的高可用性,又要考慮技術(shù)的可行性和成本效益。通過遵循以上3 個設(shè)計原則,可以在災(zāi)難發(fā)生時,盡可能地減少業(yè)務(wù)損失和用戶影響。
異地雙活的架構(gòu)為系統(tǒng)提供了可靠的數(shù)據(jù)服務(wù),下面從雙活架構(gòu)的設(shè)計和實現(xiàn)等幾方面進行闡述。
雙活架構(gòu)的設(shè)計步驟主要包括以下4 個步驟:業(yè)務(wù)分級、數(shù)據(jù)分類、數(shù)據(jù)同步技巧的設(shè)計和異常數(shù)據(jù)的處理[13]。通過以上步驟,可以找到需要同步的中間號業(yè)務(wù)數(shù)據(jù),并極大地降低了同步的復雜度。
4.1.1 業(yè)務(wù)分級
在設(shè)計異地雙活架構(gòu)時,首先需要對業(yè)務(wù)進行分級。將業(yè)務(wù)按照某個維度進行優(yōu)先級排序,優(yōu)先保證TOP3 異地多活[13]。TOP3 通常是指對企業(yè)生產(chǎn)經(jīng)營具有至關(guān)重要作用的業(yè)務(wù),如訂單、庫存、支付等。通過業(yè)務(wù)分級,可以幫助我們確定哪些業(yè)務(wù)需要進行雙活備份,哪些業(yè)務(wù)可以采用其他手段進行備份。同時,還可以優(yōu)先保證核心業(yè)務(wù)的數(shù)據(jù)進行雙活,以確保系統(tǒng)的持續(xù)可用性。
中間號系統(tǒng)主要包括通話模塊、短信模塊、媒體模塊和話單模塊。這些模塊共同構(gòu)成了一個完整的中間號系統(tǒng),實現(xiàn)了電話通信、短信傳遞和多媒體處理等功能。其中,話單模塊作為通話模塊、短信模塊和媒體模塊的最終收集點,對于整個系統(tǒng)的運行至關(guān)重要。從訪問量和收入來源兩個方面來看,話單模塊無疑是最為關(guān)鍵的部分。這是因為話單負責記錄和整理用戶在通話、短信和多媒體模塊中產(chǎn)生的各種數(shù)據(jù),如通話時長、短信數(shù)量、多媒體傳輸量等。這些數(shù)據(jù)在一定程度上反映了用戶的活躍度和使用習慣,從而為運營商提供了制定合理收費策略和優(yōu)化服務(wù)的重要依據(jù)。從核心場景的角度來分析,通話和短信模塊同樣具有非常重要的地位。作為電話通信和文本通信的基本功能,通話和短信模塊直接關(guān)系到用戶對中間號系統(tǒng)的滿意度和忠誠度。因此,保證通話和短信模塊的穩(wěn)定性、高效性和安全性是優(yōu)化中間號系統(tǒng)的關(guān)鍵。
綜上所述,在中間號系統(tǒng)中,通話模塊、短信模塊和話單模塊的數(shù)據(jù)具有較高的重要性。為了提高系統(tǒng)的運行效率和用戶體驗,我們需要重點關(guān)注這兩個模塊的數(shù)據(jù)同步和安全,以實現(xiàn)更加高效和穩(wěn)定的中間號服務(wù)。
4.1.2 數(shù)據(jù)分類
在確定了需要進行雙活備份的業(yè)務(wù)之后,我們需要對業(yè)務(wù)的關(guān)鍵數(shù)據(jù)進行分類[13]。數(shù)據(jù)分類是根據(jù)數(shù)據(jù)的特點和需求,將數(shù)據(jù)分成不同的類別,以便于進行同步和備份。可以將數(shù)據(jù)按照數(shù)據(jù)修改量、一致性、唯一性、可丟失性、可恢復性等指標進行分類。通過數(shù)據(jù)分類,可以更好地了解不同數(shù)據(jù)的特點和需求,為后續(xù)的數(shù)據(jù)同步技術(shù)的設(shè)計提供參考依據(jù)。
根據(jù)上述概述,我們的目標數(shù)據(jù)包括通話、短信和話單數(shù)據(jù),其中,話單數(shù)據(jù)是由短信數(shù)據(jù)和通話數(shù)據(jù)生成的,具有可恢復性,可以不考慮異地備份話單數(shù)據(jù)。數(shù)據(jù)特點如表1 所示。
表1 數(shù)據(jù)類型分類
4.1.3 數(shù)據(jù)同步技巧的設(shè)計
數(shù)據(jù)同步技巧是雙活架構(gòu)中的關(guān)鍵技術(shù)之一。在設(shè)計數(shù)據(jù)同步策略時,需要針對不同類型的數(shù)據(jù)采用相應(yīng)的同步方法。對于結(jié)構(gòu)化數(shù)據(jù),可以采用數(shù)據(jù)庫復制技術(shù),通過主從同步或雙主同步的方式實現(xiàn)數(shù)據(jù)同步。在實施數(shù)據(jù)同步過程中,需要關(guān)注單路復制故障的問題,以確保數(shù)據(jù)同步的效率和準確性[13]。
根據(jù)前述數(shù)據(jù)特點,我們提出了一種多通道同步設(shè)計方案。在這個方案中,北方數(shù)據(jù)中心設(shè)有一個主備集群,南方數(shù)據(jù)中心也設(shè)有一個主備集群。每個集群都包含一個MySQL 主服務(wù)器和一個備份服務(wù)器。兩個IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)之間的主服務(wù)器通過Canal 進行雙向復制,兩個IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)之間的備份服務(wù)器也通過Canal 進行雙向復制。同時,每個IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)內(nèi)部的主備服務(wù)器之間進行單向復制。由于每個IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)內(nèi)部之間的MYSQL 數(shù)據(jù)庫是使用自帶的復制功能,所以進行雙通道復制的時候,會產(chǎn)生數(shù)據(jù)在一個集群內(nèi)交叉復制的情況,為了降低復雜度,中間號系統(tǒng)采用單通道+雙Canal 的形式進行高可用保障。具體架構(gòu)如圖1 所示。
圖1 中間號系統(tǒng)雙活架構(gòu)圖
通過雙Canal 的同步設(shè)計方案,我們可以確保數(shù)據(jù)在雙活架構(gòu)中的高可用性和一致性。當某個數(shù)據(jù)中心的主服務(wù)器發(fā)生故障時,備份服務(wù)器可以迅速接管服務(wù),Canal馬上讀取備份機器的BINLOG 進行同步,從而保證業(yè)務(wù)的連續(xù)性。雙向復制技術(shù)還可以有效降低數(shù)據(jù)傳輸延遲,提高數(shù)據(jù)同步效率。通過采用數(shù)據(jù)庫復制技術(shù)和雙Canal的同步設(shè)計方案,我們可以有效地實現(xiàn)結(jié)構(gòu)化數(shù)據(jù)的高效同步,確保業(yè)務(wù)的高可用性和一致性。在實際應(yīng)用過程中,我們密切關(guān)注單路復制故障等問題,以確保數(shù)據(jù)同步的穩(wěn)定性和準確性。
4.1.4 異常數(shù)據(jù)的處理
在雙活架構(gòu)的實現(xiàn)過程中,可能會遇到一些極端異常情況,例如網(wǎng)絡(luò)故障、硬件故障以及數(shù)據(jù)沖突等。盡管在前述章節(jié)中,我們已經(jīng)采用了單通道+雙Canal 形式的設(shè)計方案以提高系統(tǒng)的可靠性,但仍然可能出現(xiàn)兩個Canal同時發(fā)生故障的情況。然而,這種情況的出現(xiàn)概率極低,因此可以通過人工干預的方式進行補救[13]。
在應(yīng)對這類異常情況時,我們采取一些措施以降低客戶的損失,例如對當月話單進行打折收費或者當日話單收費減免。雖然這些補救措施可能會導致企業(yè)短期內(nèi)承擔較大的成本,但從長遠來看,這將有利于維護企業(yè)的良好口碑,從而在市場競爭中取得更大的收益。這種策略雖然需要企業(yè)在短期內(nèi)承擔一定成本,但在長期來看,有助于提高客戶滿意度和企業(yè)聲譽,從而實現(xiàn)更大的收益。
本節(jié)將介紹雙活架構(gòu)中兩個常見問題的解決方案。首先,通過選擇性同步來減少不必要的網(wǎng)絡(luò)傳輸和提高同步效率[17]。其次,為了解決循環(huán)復制問題,需要在源碼上做兩處改動,對同步數(shù)據(jù)進行過濾和標記。這些改動可以有效地提高同步效率和減少數(shù)據(jù)的死循環(huán)同步,保證雙活存儲架構(gòu)的高可用性和容錯性,使得原本單向同步的Canal變成可以支撐雙向同步的中間件。
4.2.1 有選擇的數(shù)據(jù)同步
首先,Canal 的全量同步和增量同步都是默認開啟的。這意味著所有數(shù)據(jù)更改都會被同步到另一個存儲節(jié)點,包括無關(guān)緊要的數(shù)據(jù)和不必要的操作。這會導致數(shù)據(jù)同步的效率低下,同時也會增加網(wǎng)絡(luò)帶寬的壓力。因此,我們可以通過選擇性同步來解決這個問題。具體來說,可以配置需要同步的數(shù)據(jù)表,以減少不必要的網(wǎng)絡(luò)傳輸和提高同步效率。此外,由于數(shù)據(jù)庫表的數(shù)量通常非常龐大而且是重要的,因此對于刪除操作的DML 語句和修改數(shù)據(jù)庫結(jié)構(gòu)的DDL 語句,是不允許操作的,尤其是DDL 語句執(zhí)行期間會鎖住整個表,影響業(yè)務(wù)系統(tǒng)。因此,改進Parser 模塊里面的LogEventConvert.parseOneRow 方法代碼,只同步新增和修改的數(shù)據(jù)庫操作,可以減少不必要的BINLOG日志傳輸,提高同步效率。
4.2.2 循環(huán)復制問題的解決
循環(huán)復制是雙活存儲架構(gòu)中常見的問題。循環(huán)復制指的是多個存儲節(jié)點之間相互同步,形成一個環(huán)狀結(jié)構(gòu),導致數(shù)據(jù)的死循環(huán)同步。這個問題會導致數(shù)據(jù)的重復復制,占用大量的帶寬。為了解決這個問題,我們需要在源碼上做兩處改動。首先,在客戶端adapter 模塊進行入庫操作時,在所有SQL 語句執(zhí)行前后對標識表retl_mark分別進行插入和修改。其次,在客戶端adapter 模塊的RdbSyncService.sync 方法里增加對retl_mark 表BINLOG進行過濾,避免本IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)的數(shù)據(jù)重復執(zhí)行多次,從而避免循環(huán)復制的問題。
在非正式環(huán)境中,基于Canal 實現(xiàn)的中間號雙活架構(gòu)成功地進行了海量數(shù)據(jù)的試驗,并打通了南北地域的通話數(shù)據(jù)和短信數(shù)據(jù)的限制。在數(shù)據(jù)同步過程中,南北數(shù)據(jù)的同步時延通常在100~200 ms 之間。盡管存在一定的時延,但話單數(shù)據(jù)最終能夠完整地同步到目標IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)的數(shù)據(jù)庫,實現(xiàn)了數(shù)據(jù)的最終一致性。然而,網(wǎng)絡(luò)波動有時會導致時延變長,達到秒級。為了降低這種額外復雜度,建議將兩個IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)機房的距離控制在100 km 以內(nèi)。這樣可以更好地控制網(wǎng)絡(luò)延遲,提高數(shù)據(jù)同步的穩(wěn)定性。
本文采用了基于Canal 的數(shù)據(jù)庫鏡像復制技術(shù),提出了一種基于數(shù)據(jù)特點來設(shè)計同步的同步方案,同時對Canal 進行了改良,使它可以進行有條件的數(shù)據(jù)同步,優(yōu)化了同步數(shù)據(jù)對網(wǎng)絡(luò)的擁塞影響,提升了用戶對中間號系統(tǒng)的認可度。該架構(gòu)的實現(xiàn)基于Canal 的二次改造,成本低廉,同步系統(tǒng)相對簡單且可靠,為運營商提供了一種同步數(shù)據(jù)的方案。