溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-05-31 13:41:52 來源:億速云 閱讀:155 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“SQL Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“SQL Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)”吧!

一、架構(gòu)綜述

通過對現(xiàn)有系統(tǒng)瓶頸的分析,我們發(fā)現(xiàn)核心缺陷集中在訂單數(shù)據(jù)緩存分散導(dǎo)致數(shù)據(jù)各端不一致,各訂單應(yīng)用則與數(shù)據(jù)庫直連又造成可擴(kuò)展性差。通過實(shí)踐我們編寫中間件抽象并統(tǒng)一了數(shù)據(jù)訪問層,以及基于數(shù)據(jù)庫部署架構(gòu)鏡像構(gòu)建了訂單緩存統(tǒng)一管理熱點(diǎn)數(shù)據(jù),解決了各端差異。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖1.1  存儲系統(tǒng)架構(gòu)圖

二、應(yīng)用場景

1、新單秒級各端同步

從訂單的提交到各端可見的速度為存儲服務(wù)的核心指標(biāo)之一,我們對數(shù)據(jù)鏈的主要環(huán)節(jié)進(jìn)行了優(yōu)化,覆蓋了新單同步、消息實(shí)時(shí)推送、查詢索引構(gòu)建以及數(shù)據(jù)平臺離線歸檔等主要環(huán)節(jié),使大系統(tǒng)內(nèi)數(shù)據(jù)到達(dá)速度在3秒以內(nèi),即用戶剛下完單即可跳轉(zhuǎn)我攜列表可見。

當(dāng)新用戶創(chuàng)單時(shí),同步服務(wù)作為數(shù)據(jù)鏈入口將用戶訂單數(shù)據(jù)通過中間件寫入訂單庫,此時(shí)中間件同時(shí)完成訂單緩存的構(gòu)建;

當(dāng)訂單完成入庫行為和熱點(diǎn)數(shù)據(jù)構(gòu)建后拋訂單消息,實(shí)時(shí)輸出給各子系統(tǒng);

當(dāng)新單入庫完畢即刻構(gòu)建訂單明細(xì)信息的ES索引,為第三方提供檢索支持;

最后數(shù)據(jù)平臺T+1實(shí)施當(dāng)日數(shù)據(jù)的歸檔供BI等各類離線業(yè)務(wù)使用。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖2.1 數(shù)據(jù)鏈

2、自動發(fā)單與工作臺

對客、商、員工工作臺三端的支持是訂單存儲系統(tǒng)的基本角色,圖2.1數(shù)據(jù)鏈在新單提交后為自動發(fā)單與工作臺起到的銜接作用功不可沒。自動發(fā)單即在客人提交訂單后,以最快的響應(yīng)速度向商戶發(fā)送訂單明細(xì)信息進(jìn)行核實(shí)貨位、確認(rèn)訂單等流程。工作臺則協(xié)助員工介入流程及時(shí)獲取訂單處理人工事件。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖2.2 基于存儲系統(tǒng)的發(fā)單與工作臺關(guān)系(縮略細(xì)節(jié))

3、查詢與數(shù)據(jù)分析

基于訂單數(shù)據(jù)為核心的主要分為在線查詢和數(shù)據(jù)分析兩條業(yè)務(wù)線,以對詳情查詢?yōu)槔?,訪問QPS終年保持在高位,每逢假期高峰則容易造成查詢瓶頸,根因復(fù)盤后在本次架構(gòu)升級中我們做了調(diào)整來優(yōu)化相關(guān)場景的高可用性。

  • 在線查詢以訂單緩存為主,訂單提交即構(gòu)建熱點(diǎn)緩存紓解查詢壓力,并可按配置時(shí)間參數(shù)長時(shí)段有效。

  • 非在線查詢場景,以實(shí)時(shí)消息推送并結(jié)合Hive數(shù)倉T+1方式交付,凡需要長周期訂單數(shù)據(jù)的場合(例如實(shí)時(shí)報(bào)表)均接入訂單消息實(shí)時(shí)計(jì)算。離線BI按年度等大批量數(shù)據(jù)分析時(shí)使用Hive表,并每日凌晨低峰時(shí)段以從庫低頻訪問的方式實(shí)施數(shù)據(jù)同步。

如此以上,我們將訂單主庫的訪問保護(hù)在訂單緩存、實(shí)時(shí)消息、Hive數(shù)倉三駕馬車之后,與業(yè)務(wù)盡最大可能的解耦。

三、系統(tǒng)升級實(shí)踐 

在對攜程核心存儲系統(tǒng)進(jìn)行更新?lián)Q代的過程中,貫穿全程需要做到的是熱遷移,并達(dá)成所有操作對數(shù)據(jù)鏈路上的各應(yīng)用透明無損的目標(biāo)。我們的設(shè)計(jì)通盤分析了集團(tuán)數(shù)據(jù)鏈路的特性,由訂單緩存系統(tǒng)提供數(shù)據(jù)庫鏡像降低應(yīng)用與數(shù)據(jù)庫的直連耦合,繼而再通過中間件對應(yīng)用透明掉數(shù)據(jù)源于SQLServer / MySQL的物理關(guān)系,提供底層熱遷移的操作空間。

結(jié)合無損遷移的工藝設(shè)計(jì),注重對每一筆數(shù)據(jù)庫流量的可見及可控,支持全庫、Shard級、表級、CRUD操作級的流量分配策略,提供了底層數(shù)據(jù)遷移足夠的實(shí)施手段。數(shù)倉銜接設(shè)計(jì)則側(cè)重于解決數(shù)據(jù)平臺百億級離線數(shù)據(jù)與雙庫在線期間的同步問題,以及解決全量接入MySQL期間產(chǎn)生的數(shù)據(jù)問題。

以下將分三個(gè)部分分享我們在這一過程中學(xué)到的經(jīng)驗(yàn)。

1、分布式訂單緩存

隨著業(yè)務(wù)發(fā)展,用戶數(shù)和訪問量越來越大,訂單系統(tǒng)應(yīng)用和服務(wù)器的壓力也與日俱增。在沒有引入訂單緩存之前,每個(gè)應(yīng)用獨(dú)立連接數(shù)據(jù)庫,造成查詢出來的數(shù)據(jù)無法在應(yīng)用間共享,并且DB每秒查詢量和連接數(shù)都有上限,而酒店核心交易鏈路基于DB存儲,存在單點(diǎn)故障風(fēng)險(xiǎn)。

經(jīng)過埋點(diǎn)數(shù)據(jù)分析,訂單系統(tǒng)是典型的讀多寫少,為了共享熱點(diǎn)查詢數(shù)據(jù)以及降低DB負(fù)載,一個(gè)有效的辦法就是引入緩存,如圖3.1,用戶的請求過來時(shí),優(yōu)先查詢緩存,如果存在緩存數(shù)據(jù),則直接返回結(jié)果;緩存沒有命中,則去查詢DB,根據(jù)配置策略校驗(yàn)DB結(jié)果數(shù)據(jù),校驗(yàn)通過則將DB數(shù)據(jù)寫入緩存留作后續(xù)查詢使用,否則不寫入緩存,最后返回DB查詢結(jié)果。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖3.1 訂單緩存基本設(shè)計(jì)

關(guān)于引入新的緩存組件后的硬件開銷,可通過收斂原來各應(yīng)用分散的硬件資源來降低總成本,但還會因?yàn)橹行幕芾韼砜捎眯蕴魬?zhàn)以及數(shù)據(jù)一致性等問題,故需要充分對現(xiàn)有系統(tǒng)進(jìn)行容量評估、流量估算和緩存表價(jià)值分析。只緩存訪問量高的熱點(diǎn)數(shù)據(jù)表,通過恰當(dāng)?shù)木彺娼Y(jié)構(gòu)設(shè)計(jì)、數(shù)據(jù)壓縮和緩存淘汰策略,最大程度提高緩存命中率,在緩存容量、硬件成本和可用性之間做好權(quán)衡。

傳統(tǒng)的緩存設(shè)計(jì),是一條數(shù)據(jù)庫表記錄對應(yīng)一條緩存數(shù)據(jù)。而在訂單系統(tǒng)中,一個(gè)訂單查詢多表的場景很常見,如果采用傳統(tǒng)設(shè)計(jì),在一次用戶查詢中,Redis的訪問次數(shù)是隨著表數(shù)量增加的,這種設(shè)計(jì)網(wǎng)絡(luò)IO較大并且耗時(shí)較長。在盤點(diǎn)表維度流量數(shù)據(jù)時(shí),我們發(fā)現(xiàn)有些表經(jīng)常一起查詢,不到30%的表其查詢流量超過90%,在業(yè)務(wù)上完全可以劃分為同一個(gè)抽象領(lǐng)域模型,然后基于hash結(jié)構(gòu)進(jìn)行存儲,如圖3.2,以訂單號作為key,領(lǐng)域名稱作為field,領(lǐng)域數(shù)據(jù)作為value。

這樣無論是單表還是多表查詢,每個(gè)訂單都只需要訪問一次Redis,即減少了key,又減少了多表查詢次數(shù),提升了性能。同時(shí)value基于protostuff進(jìn)行壓縮,還減少了Redis的存儲空間,以及隨之而來的網(wǎng)絡(luò)流量開銷。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖3.2 基于domain的存儲結(jié)構(gòu)簡述

2、無損遷移工藝

如何做到無損熱遷移是整個(gè)項(xiàng)目最具挑戰(zhàn)性的地方。在工藝設(shè)計(jì)之前我們的前置工作首先完成了中間件的開發(fā),通過中間件將數(shù)據(jù)庫與業(yè)務(wù)層應(yīng)用一分為二。其次抽象Dao層實(shí)現(xiàn)領(lǐng)域化,并由數(shù)據(jù)領(lǐng)域?qū)酉驊?yīng)用提供數(shù)據(jù)服務(wù),領(lǐng)域之下適配SQLServer和MySQL兩種數(shù)據(jù)庫并統(tǒng)一封裝。以此為基礎(chǔ)才能為以下述工藝設(shè)計(jì)實(shí)施無損熱遷移。

  • SQLServer和MySQL雙庫在線,實(shí)施雙寫,主寫SQLServer,同步副寫MySQL,如果SQLServer操作失敗則整體失敗,回滾雙寫事務(wù)。

  • SQLServer和MySQL之間增加一路同步Job,實(shí)時(shí)查詢SQLServer最近時(shí)間窗口變更的數(shù)據(jù)進(jìn)行一致性校驗(yàn)MySQL中的條目,差異點(diǎn)追齊,可以確保雙寫期間不可預(yù)期的兩邊不一致,特別是還殘有直連寫SQLServer應(yīng)用的階段特別有用。

  • 中間件設(shè)計(jì)有配置系統(tǒng),支持任一主要查詢維度可按配置精準(zhǔn)的將數(shù)據(jù)源定向到SQLServer或MySQL,并可控制是否讀取后加載到訂單緩存。初期設(shè)定只加載SQLServer數(shù)據(jù)源,避免因雙庫間的數(shù)據(jù)不一致而造成緩存數(shù)據(jù)跳躍。并在初期可設(shè)置灰度,將小批量非核心表直連MySQL驗(yàn)證可靠性。后期數(shù)據(jù)一致性達(dá)成預(yù)期后,訂單緩存也可自由按指定數(shù)據(jù)庫加載緩存。

  • 解決了查詢場景下的數(shù)據(jù)一致性問題后,流量策略支持圖3.3中任一可調(diào)控維度進(jìn)行數(shù)據(jù)庫單寫。實(shí)際項(xiàng)目中以表維度實(shí)施單寫為主,當(dāng)指定表被配置單寫MySQL后,所有涉及該表的CRUD行為全部定向MySQL,包括緩存加載源。

  • 最后通過中間件統(tǒng)一收口對外發(fā)送的訂單消息,所有消息基于中間件的CUD操作發(fā)送與物理數(shù)據(jù)庫無關(guān),這樣實(shí)現(xiàn)消息的數(shù)據(jù)源透明,且可聯(lián)動以上所有工藝操作,數(shù)據(jù)鏈保持一致。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖3.3  操作工藝簡介

3、數(shù)倉銜接

為了方便理解生產(chǎn)數(shù)據(jù)到數(shù)據(jù)倉庫ODS層數(shù)據(jù)的遷移,做到對下游透明,這里簡單介紹一下常規(guī)數(shù)據(jù)倉庫的分層體系。通常數(shù)據(jù)倉庫主要分為五層:ODS(原始數(shù)據(jù)層)、DIM(維度)、EDW(企業(yè)數(shù)倉)、CDM(通用模型層)、ADM(應(yīng)用模型層),

如下圖所示:

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖3.4  數(shù)據(jù)倉庫分層結(jié)構(gòu)

從圖3.4上可以看出,數(shù)據(jù)倉庫各層都依賴ODS層的數(shù)據(jù),為了不影響數(shù)據(jù)平臺所有應(yīng)用,我們只需要將原來訂單庫ODS層數(shù)據(jù)源從SQLServer遷移到MySQL庫即可。

從圖上很直觀的看出,遷移只需換個(gè)數(shù)據(jù)源不是很麻煩,但是為了保證數(shù)據(jù)質(zhì)量,我們做了很多的前置工作,比如:DBA預(yù)先將生產(chǎn)數(shù)據(jù)同步到生產(chǎn)MySQL庫、MySQL數(shù)據(jù)實(shí)時(shí)同步、生產(chǎn)兩側(cè)數(shù)據(jù)一致性校驗(yàn)、MySQL側(cè)數(shù)據(jù)同步到ODS層、ODS層數(shù)據(jù)一致性校驗(yàn)及原有ODS層同步Job數(shù)據(jù)源切換等。

其中,生產(chǎn)兩側(cè)數(shù)據(jù)一致性校驗(yàn)和數(shù)據(jù)倉庫ODS層數(shù)據(jù)一致性校驗(yàn)最為復(fù)雜,耗時(shí)也最長,要確保每張表、每個(gè)字段都要一致時(shí)才能切換數(shù)據(jù)源。但是,從實(shí)際操作過程中,卻做不到完全一致。根據(jù)實(shí)際情況,適當(dāng)處理時(shí)間類型、浮點(diǎn)值精度及小數(shù)位等。

下面介紹一下整體流程:

首先,對于線上數(shù)據(jù)一致校驗(yàn),我們開發(fā)了在線同步Job,將SQLServer的數(shù)據(jù)和MySQL數(shù)據(jù)進(jìn)行比較,發(fā)現(xiàn)不一致時(shí),就將MySQL的數(shù)據(jù)以SQLServer數(shù)據(jù)為基準(zhǔn)更新掉,確保兩邊數(shù)據(jù)的一致性。

其次,對于離線數(shù)據(jù)一致性校驗(yàn),我們和數(shù)據(jù)倉庫同事合作把MySQL側(cè)數(shù)據(jù)同步到ODS層(以庫名區(qū)分是SQLServer還是MySQL的表),并且將定時(shí)跑的任務(wù)和SQLServer側(cè)任務(wù)在時(shí)間上盡量一致。兩側(cè)數(shù)據(jù)都準(zhǔn)備好后,我們開發(fā)了離線數(shù)據(jù)校驗(yàn)?zāi)_本生成器,根據(jù)數(shù)據(jù)倉庫元數(shù)據(jù),為每張表生成一個(gè)同步Job,將其部署到調(diào)度平臺。

同步任務(wù)會依賴兩側(cè)ODS層同步數(shù)據(jù),T+1數(shù)據(jù)同步完成后,執(zhí)行一致性校驗(yàn),將不一致的訂單號記錄到不一致明細(xì)表中,并統(tǒng)計(jì)不一致的數(shù)據(jù)量,將結(jié)果保存到統(tǒng)計(jì)表中。然后在自助報(bào)表平臺制作一個(gè)報(bào)表,將每天統(tǒng)計(jì)的不一致的表及不一致量發(fā)送到郵箱,我們每天對不一致的表進(jìn)行排查找出問題,調(diào)整比較策略,更新比較Job。大致流程如下:

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖3.5  一致性校驗(yàn)整體流程

最后,隨著線上和離線數(shù)據(jù)逐步趨于一致后,我們將原先SQLServer同步到ODS層Job的數(shù)據(jù)源切換到MySQL。這里可能有同學(xué)會有疑問:為什么不直接使用MySQL側(cè)ODS層的表呢?原因是,經(jīng)過統(tǒng)計(jì),依賴原先ODS層表的Job有上千個(gè)之多,如果讓依賴Job切換到MySQL側(cè)ODS表,修改工作量非常大,所以我們直接將原來的ODS層同步數(shù)據(jù)源直接切換成MySQL。

實(shí)際操作中,切數(shù)據(jù)源并不能一次全部切完,我們分三批進(jìn)行,先找十幾個(gè)不那么重要的表作為第一批,切完后運(yùn)行兩周,并收集下游數(shù)據(jù)問題的反饋。第一批表順利切完兩周后,我們沒收到下游報(bào)數(shù)據(jù)問題,說明數(shù)據(jù)質(zhì)量沒問題。然后再將剩余的幾百張表按重要程度分兩批繼續(xù)切,直到切完。

至此,我們完成了訂單庫從SQLServer遷移到MySQL在數(shù)據(jù)倉庫層的遷移工作。

四、核心問題精編

實(shí)際上再周密的分析與設(shè)計(jì),總是難免遇到執(zhí)行過程中的各種挑戰(zhàn)。我們總結(jié)了一些經(jīng)典問題,雖然通過技術(shù)手段最終解決了這些大大小小問題并達(dá)成了目標(biāo),但是相信各位看官必定還有更好的解決方案,我們樂見共同學(xué)習(xí)與進(jìn)步。

1、SQLServer & MySQL 流量遷移如何細(xì)粒度監(jiān)控

訂單系統(tǒng)涉及到的應(yīng)用和表數(shù)量眾多,一個(gè)應(yīng)用對應(yīng)1到n張表,一張表又對應(yīng)1到n個(gè)應(yīng)用,是典型的多對多關(guān)系。如圖4.1,對于上層應(yīng)用來說,從一個(gè)SQLServer數(shù)據(jù)庫,切換到另一個(gè)MySQL數(shù)據(jù)庫,其基本流程參照操作工藝章節(jié)至少分為以下幾步:

  • 從單寫SQLServer變成雙寫SQLServer和MySQL

  • 從單讀SQLServer變成單讀MySQL

  • 從雙寫SQLServer和MySQL變成單寫MySQL

  • 下線SQLServer

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖4.1 應(yīng)用和數(shù)據(jù)庫以及表的關(guān)系圖

在生產(chǎn)環(huán)境更換數(shù)據(jù)庫系統(tǒng),就像在高速公路上不停車換輪胎,需要維持原有的車速不變,且對用戶無感,否則后果不敢設(shè)想。

在切換工藝中雙寫、單讀和單寫流程,環(huán)環(huán)相扣,步步相依,作為配套設(shè)計(jì)監(jiān)控手段必須確認(rèn)上一個(gè)操作達(dá)到預(yù)期效果才能進(jìn)行下一個(gè)。如果跳過或者沒有切換干凈就貿(mào)然進(jìn)行下一步,比如還沒有雙寫完全一致,就開始讀MySQL數(shù)據(jù),可能造成查無此數(shù)據(jù)或者查到臟數(shù)據(jù)!那么就需要對每一個(gè)CRUD操作的讀寫進(jìn)行監(jiān)控,在遷移過程中做到360度無死角可視化流量細(xì)分控制,所見即所得。具體的做法如下:

  • 所有應(yīng)用接入中間件,CRUD由中間件根據(jù)配置控制讀寫哪個(gè)DB的哪張表;

  • 每一個(gè)讀寫操作的詳細(xì)信息均寫入ES,在Kibana和Grafana上可視化展示,并且通過DBTrace,可以知道每條SQL是在哪個(gè)DB上執(zhí)行;

  • 按照應(yīng)用級別逐步配置雙寫DB,通過同步Job實(shí)時(shí)比對、修復(fù)和記錄兩側(cè)DB差異,再通過離線T+1校驗(yàn)雙寫中出現(xiàn)的最終不一致,如此往復(fù)直到雙寫一致;

  • 雙寫一致之后,就開始逐步將讀SQLServer切換到讀MySQL,通過ES監(jiān)控和DBTrace確認(rèn)完全沒有SQLServer讀,則表明單讀MySQL完成,考慮到自增主鍵情況,我們采取按照表維度,按批次斷寫SQLServer,直至所有表都單寫MySQL。

綜上所述,基本方案為通過中間件為管道為所有接入的應(yīng)用統(tǒng)一埋點(diǎn),通過實(shí)時(shí)展示應(yīng)用層的行為觀察流量分布,并結(jié)合公司數(shù)據(jù)庫側(cè)Trace的可視化工具核實(shí)應(yīng)用的流量切換行為與數(shù)據(jù)庫實(shí)際QPS及負(fù)載浮動保持一致來監(jiān)督遷移任務(wù)。

2、如何解決雙寫期間DB一致性問題

酒店的訂單庫有著二十年左右歷史,經(jīng)年累積,跨部門和酒店內(nèi)部多個(gè)團(tuán)隊(duì)直接或間接依賴訂單庫SQLServer,要想切換到MySQL,就得先解決雙寫DB一致性問題,不一致主要體現(xiàn)在以下兩點(diǎn):

  • 雙寫時(shí)實(shí)際僅單寫了SQLServer,漏寫MySQL;

  • 雙寫SQLServer和MySQL成功,并發(fā)、不可靠網(wǎng)絡(luò)、GC等發(fā)生時(shí)MySQL數(shù)據(jù)有幾率和SQLServer不一致。

關(guān)于雙寫數(shù)據(jù)一致性的保證,我們基于同步Job將SQLServer數(shù)據(jù)為準(zhǔn)線,根據(jù)最后更新時(shí)間,拉取兩側(cè)DB數(shù)據(jù)進(jìn)行比對,如果不一致則修復(fù)MySQL的數(shù)據(jù)并將不一致信息寫入ES,供后續(xù)排查根因。

但也因?yàn)橐肓祟~外的Job操作MySQL數(shù)據(jù),帶來了新的問題,那就是多表雙寫時(shí),因?yàn)楹臅r(shí)翻倍,Job發(fā)現(xiàn)SQLServer有數(shù)據(jù)而MySQL沒有,就立即修復(fù)了MySQL數(shù)據(jù),造成雙寫失敗。所以雙寫部分失敗又加上了Failover機(jī)制,通過拋送消息,觸發(fā)新一輪的比對和修復(fù)工作,直到兩側(cè)DB數(shù)據(jù)完全一致。

同步Job和Failover消息機(jī)制雖然可以讓數(shù)據(jù)最終一致,但畢竟有秒級的間隔,兩側(cè)數(shù)據(jù)是不一致的,并且對于眾多應(yīng)用的各種場景,難免會有遺漏時(shí)單寫SQLServer。對于這些漏寫MySQL的地方,通過DBTrace是無法找到的,因?yàn)闊o法確定一個(gè)CUD操作只寫入SQLServer,而未寫入MySQL。那么有沒有辦法事前就能找出漏寫MySQL的場景呢,確實(shí)被我們找出來一點(diǎn),那就是更換數(shù)據(jù)庫連接串,接入中間件的應(yīng)用使用新連接串,然后找出所有使用舊連接串操作SQLServer的SQL,就能準(zhǔn)確定位出漏寫MySQL的流量了。

最終,我們將雙寫DB不一致率從十萬分之二逐步降低到了幾乎為0,為什么是幾乎呢,因?yàn)镈B的一些特性差異問題,會天然的導(dǎo)致數(shù)據(jù)無法完全一致,這個(gè)在后續(xù)內(nèi)容會有詳細(xì)的論述。

3、引入訂單緩存后導(dǎo)致的數(shù)據(jù)不同步問題處理

引入緩存之后,就涉及到對緩存進(jìn)行寫入或者更新,業(yè)界常見的做法分為以下幾種:

  • 先寫DB再寫緩存

  • 先寫緩存再寫DB

  • 先刪緩存再寫DB

  • 先寫DB再刪緩存

在具體實(shí)施上還會進(jìn)行雙刪緩存或者延遲雙刪緩存,此處不再比較各種做法的優(yōu)劣。我們采用的是先寫DB再刪緩存方案,對于數(shù)據(jù)敏感表,會進(jìn)行延遲雙刪,后臺的同步Job定時(shí)比對、修復(fù)和記錄數(shù)據(jù)庫數(shù)據(jù)與Redis數(shù)據(jù)的差異,雖然設(shè)計(jì)上已經(jīng)能保證最終一致性,但是在前期還是出現(xiàn)過大量的數(shù)據(jù)不一致。主要體現(xiàn)在以下幾個(gè)方面:

  • 應(yīng)用有場景未接入中間件,對DB進(jìn)行CUD操作之后,漏刪除緩存;

  • 寫DB后刪除緩存延遲導(dǎo)致讀取到緩存臟數(shù)據(jù),比如不可靠網(wǎng)絡(luò)、GC等造成刪緩存延遲;

  • 寫DB后刪除緩存失敗導(dǎo)致讀取到緩存臟數(shù)據(jù),比如Redis主從切換期間,只能讀不可寫。

而為了解決緩存一致性問題,如圖4.2,我們在原有的緩存和DB基礎(chǔ)上,增加了樂觀鎖和CUD施工標(biāo)記,來限制并發(fā)情況下同時(shí)存在加載數(shù)據(jù)到緩存相互覆蓋的行為,以及對當(dāng)前被查數(shù)據(jù)正在進(jìn)行CUD操作的感知。在此兩種場景未結(jié)束期間可以做到Query流量直連DB,通過基于樂觀鎖的最后寫入者獲勝機(jī)制解決競爭問題。最終我們的緩存不一致率從百萬分之二控制到了千萬分之三。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

圖4.2 緩存一致性解決

圖4.2當(dāng)查詢未命中緩存,或當(dāng)前存在該數(shù)據(jù)的樂觀鎖或施工標(biāo)記時(shí),當(dāng)次查詢直連DB,直至相關(guān)事務(wù)完成后放開緩存數(shù)據(jù)自動加載功能。

4、存量訂單數(shù)據(jù)如何一次性校準(zhǔn)

項(xiàng)目啟動初期我們對MySQL進(jìn)行了最近N年數(shù)據(jù)的一次性鋪底,這就產(chǎn)生了在雙寫階段無法校準(zhǔn)的如下兩個(gè)場景的數(shù)據(jù):

  • 因生產(chǎn)上訂單庫預(yù)置保留近N年的數(shù)據(jù),負(fù)責(zé)清理備份的Job在接入中間件前,MySQL已存在的N年外的這批數(shù)據(jù)無法被策略覆蓋而清理掉。

  • 所有應(yīng)用接中間件花了很長時(shí)間,接中間件雙寫前數(shù)據(jù)有可能不一致的,需要全部應(yīng)用接中間件和全部表雙寫后,對之前的數(shù)據(jù)進(jìn)行一次性修復(fù)。

針對第一點(diǎn),我們開發(fā)了MySQL數(shù)據(jù)專項(xiàng)清理Job,由于訂單數(shù)據(jù)庫是多Shard的,Job內(nèi)部根據(jù)實(shí)際Shard數(shù)設(shè)置核心線程總量,每個(gè)線程分別負(fù)責(zé)對應(yīng)Shard中的指定表進(jìn)行清理,并行開多臺服務(wù)器分發(fā)任務(wù)進(jìn)行清理,通過速度控制既保證了效率又不影響生產(chǎn)上數(shù)據(jù)庫的負(fù)載。

針對第二點(diǎn),在所有應(yīng)用接中間件和所有表實(shí)現(xiàn)雙寫后,通過調(diào)整線上同步Job掃描的開始時(shí)間戳,對存量訂單數(shù)據(jù)進(jìn)行修復(fù)。修復(fù)時(shí)特別注意的是,掃描數(shù)據(jù)要按時(shí)間段分片處理,防止加載數(shù)據(jù)太多導(dǎo)致訂單庫服務(wù)器CPU太高。

5、一些數(shù)據(jù)庫特性差異問題

在如此龐大的系統(tǒng)下進(jìn)行數(shù)據(jù)庫熱遷移,我們就必須了解不同數(shù)據(jù)庫之間的差異與不同,做到知己知彼,對癥下藥。MySQL與SQLServer雖同為時(shí)下流行的關(guān)系型數(shù)據(jù)庫,均支持標(biāo)準(zhǔn)化SQL查詢,但在細(xì)枝末節(jié)上還是有些許差異。下面我們通過遷移中所面臨的問題來具體分析一下。

1)自增鍵問題

為保證數(shù)據(jù)自增序號一致,不能讓兩個(gè)數(shù)據(jù)庫各自去進(jìn)行自增,否則一旦不一致就要面臨修數(shù)據(jù)甚至更大風(fēng)險(xiǎn)。因此,在數(shù)據(jù)雙寫時(shí),我們將SQLServer寫入后生成的自增id,回寫入MySQL自增列,在數(shù)據(jù)單寫MySQL時(shí)直接使用MySQL生成自增id值。

2)日期精度問題

雙寫后為了保證數(shù)據(jù)一致性,要對兩側(cè)數(shù)據(jù)進(jìn)行一致性校驗(yàn),類型為Date、DateTime、Timestamp的字段,由于保存精度不一致,在對比時(shí)就需要做特殊處理,截取到秒進(jìn)行比較。

3)XML字段問題

SQLServer中支持XML數(shù)據(jù)類型,而MySQL 5.7不支持XML類型。在使用varchar(4000)代替后,遇到MySQL數(shù)據(jù)寫入失敗,但同步Job將SQLServer數(shù)據(jù)回寫MySQL時(shí)又能正常寫入的案例。經(jīng)過分析,程序在寫入時(shí)會將未壓縮的XML字符串寫入,SQLServer XML類型會自動壓縮并存儲,但MySQL并不會,導(dǎo)致長度超過4000的寫入操作失敗,SQLServer壓縮后長度小于4000,又能夠正?;貙慚ySQL。為此我們提出應(yīng)對措施,寫入前壓縮并校驗(yàn)長度,非重要字段截取后再存儲,重要字段優(yōu)化存儲結(jié)構(gòu)或更換字段類型。

下面列舉一些遷移過程中常見的注意點(diǎn)。

SQL?Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)

五、預(yù)警實(shí)踐

我們的預(yù)警實(shí)踐并不局限于項(xiàng)目推進(jìn)期間的監(jiān)控訴求,如何在百億級數(shù)據(jù)中周期掃描數(shù)據(jù)寫入的異常,完成項(xiàng)目期間雙寫數(shù)據(jù)一致率的復(fù)核,如何實(shí)時(shí)監(jiān)控與預(yù)警訂單庫每個(gè)分片上訂單寫入量的正常趨勢,如何定期驗(yàn)收/核驗(yàn)整套系統(tǒng)的高可用性將在以下篇幅中描述。

1、百億級數(shù)據(jù)差異校驗(yàn)預(yù)警

要滿足訂單數(shù)據(jù)SQLServer遷移到MySQL庫,數(shù)據(jù)質(zhì)量是遷移的必要條件,數(shù)據(jù)一致性達(dá)不到要求就無法透明遷移,所以設(shè)計(jì)合理的校驗(yàn)方案,關(guān)乎遷移的進(jìn)度。針對數(shù)據(jù)校驗(yàn),我們分為線上和線下兩種:

  • 線上數(shù)據(jù)校驗(yàn)和預(yù)警

遷移期間我們通過同步Job,在計(jì)算出不一致數(shù)據(jù)后,將不一致的表及字段寫入ElasticSearch,再用Kibana制作出不一致數(shù)據(jù)量及不一致表所占比例的監(jiān)控看板,通過監(jiān)控看板,我們就可以實(shí)時(shí)監(jiān)控哪些表數(shù)據(jù)不一致量比較高,再根據(jù)表名稱通過DBA工具排查出哪些應(yīng)用對表進(jìn)行了CUD操作,進(jìn)一步定位漏接中間件的應(yīng)用和代碼。

在實(shí)際操作中,我們確實(shí)找出了大量未接中間的應(yīng)用并對其改造,隨著接入中間件的應(yīng)用越來越多,數(shù)據(jù)一致性逐漸提高,從監(jiān)控看板上看到不一致的量也慢慢降低。但是一致性始終沒有降低到零,原因是應(yīng)用和同步Job并發(fā)導(dǎo)致的,這個(gè)也是最令人頭疼的問題。

或許有同學(xué)會疑問,既然雙寫了為什么不停止掉同步Job呢?原因是雙寫以SQLServer為主寫,以受中間件覆蓋的CUD范圍為基準(zhǔn),除了不能保證寫入MySQL的數(shù)據(jù)百分百成功外也不能保證兩庫的數(shù)據(jù)量相等,所以需要一致性Job兜底。由于并發(fā)的存在,雖然做不到數(shù)據(jù)百分百一致,但是可以進(jìn)一步降低。

我們的做法是,一致性Job比較時(shí)設(shè)置一個(gè)5秒的穩(wěn)定線(即距離當(dāng)前時(shí)間5秒內(nèi)的數(shù)據(jù)視為不穩(wěn)定數(shù)據(jù)),訂單數(shù)據(jù)時(shí)間戳在穩(wěn)定線內(nèi)的不進(jìn)行比較,穩(wěn)定線外的比較時(shí),會再一次計(jì)算訂單數(shù)據(jù)是否在穩(wěn)定線內(nèi),如果確認(rèn)全部數(shù)據(jù)在穩(wěn)定線外,就進(jìn)行比較操作,否則放棄本次比較,由下一次調(diào)度執(zhí)行一致性校驗(yàn)。

  • 離線數(shù)據(jù)校驗(yàn)和預(yù)警

訂單庫遷移涉及到幾百張表,離線數(shù)據(jù)比較多,一年的訂單相關(guān)數(shù)據(jù)就有上百億了,對于離線數(shù)據(jù)校驗(yàn)比較有挑戰(zhàn)。我們編寫了數(shù)據(jù)一致性腳本生成器,為每張表生成一個(gè)比較腳本并部署到調(diào)度平臺,比較腳本依賴上游SQLServer和MySQL兩側(cè)的同步Job,上游Job執(zhí)行完畢后自動執(zhí)行數(shù)據(jù)比較,將不一致數(shù)據(jù)的訂單號寫到明細(xì)表中,并根據(jù)明細(xì)表統(tǒng)計(jì)出不一致量,以日報(bào)的形式發(fā)出,每天對數(shù)據(jù)不一致比較高的表排查并解決。

通常一是能修復(fù)對比腳本的瑕疵,二是發(fā)現(xiàn)離線數(shù)據(jù)問題,就這樣反復(fù)摸排解決不一致問題。對于離線數(shù)據(jù)每張表每個(gè)字段的校驗(yàn)是非常復(fù)雜的,我們編寫UDF函數(shù)進(jìn)行比較,UDF函數(shù)功能也很簡單,就是將每張表的非主鍵字段進(jìn)行拼接生成一個(gè)新字段,兩側(cè)表進(jìn)行全外連接,主鍵或者邏輯主鍵相等的記錄,生成新字段也應(yīng)該一樣,只要不一樣就視為不一致數(shù)據(jù)。這里要注意日期字段截取、數(shù)據(jù)精度及末尾為零的小數(shù)處理問題。

經(jīng)過三個(gè)多月的努力,我們排查出所有未接中間件的應(yīng)用,并將其CUD操作全部接入中間件,開啟雙寫后線上線下數(shù)據(jù)一致性逐步提高,達(dá)到了遷移數(shù)據(jù)的目標(biāo)。

2、ALL Shard 實(shí)時(shí)訂單總量監(jiān)控  

每個(gè)公司對于訂單量的監(jiān)控是不可或缺的,攜程有一個(gè)統(tǒng)一預(yù)警平臺Sitemon,它主要監(jiān)控各類訂單告警,包括酒店,機(jī)票,無線,高鐵,度假。并能按照online/offline,國內(nèi)/國際,或者支付方式單獨(dú)搜索和展現(xiàn),并對各類訂單做了告警。

訂單數(shù)據(jù)從SQLServer遷移到MySQL期間,我們梳理出來依賴訂單庫的預(yù)警策略近兩百個(gè),負(fù)責(zé)監(jiān)控的相關(guān)同事對SQL Server數(shù)據(jù)源的預(yù)警策略原樣復(fù)制一份連接MySQL數(shù)據(jù)源。以MySQL為數(shù)據(jù)源監(jiān)控告警都添加完成后,開啟報(bào)警策略,一旦訂單量異常報(bào)警,NOC會收到兩條通知,一條來源于SQLServer數(shù)據(jù)告警,一條來源于MySQL告警,如果兩邊一致,說明灰度驗(yàn)證通過。否則,不通過,需排查MySQL 監(jiān)控問題。

經(jīng)過一段時(shí)間的灰度驗(yàn)證,兩邊報(bào)警數(shù)據(jù)一致,隨著SQLServer數(shù)據(jù)表下線(即單寫MySQL數(shù)據(jù)),以SQLServer為數(shù)據(jù)源的預(yù)警策略也跟著及時(shí)下線。

3、“流浪地球”實(shí)操

為了做好系統(tǒng)安全保障工作,提高應(yīng)對突發(fā)事件的能力,必要的演練壓測等是少不了的。為此,我們制定了完備的應(yīng)急預(yù)案并定期組織開展應(yīng)急演練——流浪地球。演練項(xiàng)目包括核心/非核心應(yīng)用熔斷、DB熔斷、Redis熔斷、核心防火墻、交換機(jī)應(yīng)急切換等。

以緩存為例,為了保證緩存服務(wù)的高可用,我們在演練時(shí)會下線部分節(jié)點(diǎn)或機(jī)器甚至切斷整個(gè)Redis服務(wù),模擬緩存雪崩、緩存擊穿等場景。按照計(jì)劃,在熔斷前我們會先切斷應(yīng)用的Redis訪問,一步步降低Redis負(fù)載,然后熔斷Redis,以此檢驗(yàn)在無Redis的情況下各應(yīng)用系統(tǒng)是否能夠正常運(yùn)轉(zhuǎn)。

但在首次演練中,熔斷Redis后應(yīng)用報(bào)錯(cuò)量就急劇上升,果斷停止演練回退并查找原因。經(jīng)過分析,部分應(yīng)用Redis操作未統(tǒng)一收口,不受中間件統(tǒng)一控制,Redis熔斷后應(yīng)用隨即出現(xiàn)異常。針對這一情況,我們分析后一方面將報(bào)錯(cuò)應(yīng)用的訂單緩存訪問收口接入中間件,另一方面強(qiáng)化了中間件與Redis的弱依賴關(guān)系,支持一鍵斷開Redis操作,并完善了各項(xiàng)指標(biāo)監(jiān)控。最終在第二次演練中順利完成Redis熔斷,各業(yè)務(wù)系統(tǒng)在全流量打入MySQL的狀態(tài)下的正常運(yùn)行。在最近一次的流浪地球演練中,機(jī)房網(wǎng)絡(luò)阻斷、非核心應(yīng)用阻斷等一輪輪故障注入后,我們的系統(tǒng)更是取得了很好的預(yù)期效果。

就這樣,在一次次的演練中,我們發(fā)現(xiàn)問題,總結(jié)經(jīng)驗(yàn),優(yōu)化系統(tǒng),完善應(yīng)急預(yù)案,一步步提升系統(tǒng)應(yīng)對突發(fā)故障的能力,保證業(yè)務(wù)的連續(xù)性以及數(shù)據(jù)的完整性。做好底層數(shù)據(jù)支撐,為整個(gè)酒店訂單系統(tǒng)保駕護(hù)航。

六、未來規(guī)劃

1、訂單緩存手工調(diào)控臺

雖然我們有完善的監(jiān)控看板與預(yù)警系統(tǒng),但對于像熔斷演練、自動化故障演練、硬件故障和維護(hù)以及不可提前預(yù)知的問題,若剛好核心開發(fā)人員未能及時(shí)在現(xiàn)場響應(yīng)操作,系統(tǒng)尚不能完全自主降級可能導(dǎo)致部分性能有所下降,比如響應(yīng)耗時(shí)增加等。在將來計(jì)劃增加手工調(diào)控看板,授權(quán)后可以讓NOC或者TS進(jìn)行針對性操作,比如Redis全部或者部分集群宕機(jī),可以一鍵切割故障Redis分片,或者根據(jù)Redis已計(jì)劃中的不可用時(shí)間段來提前設(shè)置切割時(shí)間,可以最大程度保證系統(tǒng)的可控性。

2、中間件自動降級

既然可以手工進(jìn)行調(diào)控,那么我們也考慮后續(xù)可以通過一些核心指標(biāo)的監(jiān)控,比如Redis主從切換期間,正常情況是秒級,但是我們也出現(xiàn)過部分Redis 10秒以上不可寫的情況,此時(shí)可以監(jiān)控緩存與數(shù)據(jù)庫不一致的臟數(shù)據(jù)量,也可以在Redis發(fā)生故障時(shí)通過監(jiān)控響應(yīng)耗時(shí)異常的閥值來應(yīng)用一些策略,讓中間件自動降級切割掉這些故障主機(jī)保證服務(wù)的基本穩(wěn)定,然后在探測到集群指標(biāo)穩(wěn)定后再逐步嘗試恢復(fù)。

3、中間件接入Service Mesh

當(dāng)前訂單團(tuán)隊(duì)內(nèi)部是以JAR的方式使用中間件,由中間件來屏蔽數(shù)據(jù)庫底層差異和操作Redis以實(shí)現(xiàn)更復(fù)雜的功能,天然具備接入Service Mesh能力,接入后底層升級更加快速和無感、調(diào)用更加輕量化、更好與框架進(jìn)行網(wǎng)格化集成以及上云更加方便,能夠更好的支撐攜程的國際化戰(zhàn)略目標(biāo)。

到此,相信大家對“SQL Server無感系統(tǒng)遷移到MySQL怎么實(shí)現(xiàn)”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI