MySQL到HBase數(shù)據(jù)庫(kù)遷移方案

作為開(kāi)發(fā)人員跪解,我們有很大概率會(huì)遇到需要將當(dāng)前正在使用的數(shù)據(jù)庫(kù)遷移到另一個(gè)數(shù)據(jù)庫(kù)的場(chǎng)景。比如你在項(xiàng)目早期選擇了 MySQL 作為數(shù)據(jù)庫(kù) 遇伞,雖然它已經(jīng)能滿足大多數(shù)業(yè)務(wù)場(chǎng)景和性能要求字旭,但隨著你的數(shù)據(jù)量越來(lái)越大業(yè)務(wù)日趨復(fù)雜,繼續(xù)使用 MySQL 則可能成為瓶頸莺奔,這時(shí)候你可能要開(kāi)始考慮將 MySQL 替換為更適合的數(shù)據(jù)庫(kù)比如 HBase(或 Cassandra...)欣范。

對(duì)于一個(gè)在線業(yè)務(wù)系統(tǒng)來(lái)說(shuō),遷移數(shù)據(jù)庫(kù)的挑戰(zhàn)在于不僅要做到不停機(jī)無(wú)縫遷移還要保證遷移過(guò)程風(fēng)險(xiǎn)可控令哟,這也正是本文要分享的內(nèi)容恼琼,介紹如何使用功能開(kāi)關(guān)無(wú)縫、安全地實(shí)現(xiàn)數(shù)據(jù)庫(kù)遷移励饵。

遷移案例:將 MySQL 遷移到 HBase

接下來(lái)將通過(guò)一個(gè)案例介紹整個(gè)遷移的實(shí)現(xiàn)過(guò)程驳癌。某個(gè)在線消息業(yè)務(wù)由于受限于 MySQL 性能和存儲(chǔ)瓶頸,所以需要將數(shù)據(jù)遷移到 HBase 以便于進(jìn)一步擴(kuò)大業(yè)務(wù)規(guī)模役听。

1颓鲜、使用功能開(kāi)關(guān)實(shí)現(xiàn)遷移控制

我們這里假設(shè)應(yīng)用程序邏輯都是通過(guò) DAO (數(shù)據(jù)存取對(duì)象)來(lái)查詢/讀取 MySQL 持久化數(shù)據(jù)。為了能將數(shù)據(jù)存取切換到 HBase 中典予,所以第一步是編寫(xiě)一個(gè)針對(duì) HBase 的 DAO甜滨,并且和 MySQL DAO 實(shí)現(xiàn)相同的接口以提供相同數(shù)據(jù)讀寫(xiě)能力。

現(xiàn)在已經(jīng)有兩種 DAO 接口實(shí)現(xiàn)瘤袖,一種有支持 MySQL衣摩,另一種是支持 HBase。此時(shí)開(kāi)始引入我們的功能開(kāi)關(guān)管理服務(wù) FeatureProbe捂敌。

先在eatureProbe 上創(chuàng)建四個(gè) Boolean 類型功能開(kāi)關(guān)來(lái)獨(dú)立控制對(duì) MySQL 和 HBase 的讀寫(xiě)艾扮,以其中一個(gè)開(kāi)關(guān)(messages-mysql-write)為例配置如下所示:

接下來(lái)我們對(duì)外統(tǒng)一提供 saveMessage 方法保存一個(gè)消息,代碼如下所示:

public void storeMessage(Message message, FPUser fpUser) {
  if(fpClient.booleanValue('messages-mysql-write', fpUser, true)) {
    mysqlMesseageDao.save(message)
  }
  if(fpclient.BooleanValue('messages-hbase-write', fpUser, true)) {
    hbaseMesseageDao.save(message)
  }
}

需要注意的是占婉,我們?cè)试S同一消息可能會(huì)保存在兩個(gè)地方泡嘴,其目的是保證了舊存儲(chǔ)(MySQL)的完整性的同時(shí)開(kāi)始將消息寫(xiě)入新數(shù)據(jù)存儲(chǔ)。對(duì)于讀取來(lái)說(shuō)其實(shí)現(xiàn)思路大致和存儲(chǔ)類似逆济,例如實(shí)現(xiàn)一個(gè)能根據(jù) ID 查詢消息的方法酌予,代碼如下所示:

public Message findMessageById(Long id, FPUser fpUser)  {
  // 同時(shí)獲取查詢 mysql 和 hbase 的開(kāi)關(guān)結(jié)果
  boolean shouldReadMySQL = fpClient.booleanValue('events-mysql-read', fpUser, true)
  boolean shouldReadHbase = fpClient.booleanValue('events-hbase-read', fpUser, true)
  if (shouldReadMySQL && shouldReadHbase) { // 當(dāng)開(kāi)關(guān)被同時(shí)開(kāi)啟時(shí),將對(duì)比兩者結(jié)果奖慌,但仍然返回舊存儲(chǔ)數(shù)據(jù)
    mysqlMessage = mysqlMessageDao.findMessageById(id)
    hbaseMessage = hbaseMessageDao.findMessageById(id)
    if(deepEqualsEntity(mysqlMessage, hbaseMessage)) {
      logger.error(
        "MySQL and Hbase message differ: mysql: {}, hbase: {}", 
        mysqlMessage, 
        hbaseMessage)
    }
    return mysqlMessage
  } else if (shouldReadMySQL) { // 只從 MySQL 查詢
    return mysqlMessageDao.findMessageById(id)
  } else { // 只從 HBase 中查詢
    return hbaseMessageDao.findMessageById(id)
  }
}

這里的點(diǎn)在于抛虫,我們檢查兩個(gè)“讀取”的開(kāi)關(guān)結(jié)果,當(dāng)發(fā)現(xiàn)兩者都啟用時(shí)简僧,我們會(huì)分別兩個(gè)數(shù)據(jù)庫(kù)讀取數(shù)據(jù)建椰,并比較結(jié)果是否一致,當(dāng)發(fā)現(xiàn)不一致時(shí)涎劈,我們會(huì)記錄錯(cuò)誤广凸,并最終返回舊存儲(chǔ)(MySQL)中的數(shù)據(jù)阅茶。

2、漸進(jìn)式放量遷移

現(xiàn)在我們已經(jīng)將從新老存儲(chǔ)讀寫(xiě)的代碼封裝在功能開(kāi)關(guān)中谅海,接下來(lái)需要部署代碼并進(jìn)行測(cè)試脸哀。此時(shí)只需要關(guān)閉 HBase 讀寫(xiě)開(kāi)關(guān),并打開(kāi) mysql 讀寫(xiě)開(kāi)關(guān)扭吁,便可以安全地將代碼部署上線撞蜂。

我們測(cè)試遷移時(shí),只需要在 FeatureProbe 上修改 HBase “寫(xiě)開(kāi)關(guān)”的人群規(guī)則侥袜,僅為特定用戶 QA 開(kāi)啟 蝌诡,此時(shí)只有 QA 的消息會(huì)存儲(chǔ)到 HBase,過(guò)程中觀察性能指標(biāo)和錯(cuò)誤日志枫吧,如果一切符合預(yù)期浦旱,進(jìn)一步修改人群規(guī)則將寫(xiě) HBase 在更多的用戶上生效,直到所有用戶的 “寫(xiě)操作” 均同時(shí)寫(xiě)入了兩個(gè)數(shù)據(jù)庫(kù)九杂。

當(dāng)我們寫(xiě)入性能感到滿意時(shí)颁湖,此時(shí)可以開(kāi)始為一小部分用戶打開(kāi) HBase 的讀取開(kāi)關(guān),然后再次觀察性能指標(biāo)和錯(cuò)誤日志例隆,其中特別需要關(guān)注是否有** “MySQL and Hbase message differ...”的日志來(lái)確保兩個(gè)存儲(chǔ)數(shù)據(jù)的一致性甥捺。當(dāng)然,這里即便我們看到數(shù)據(jù)不一致的錯(cuò)誤日志镀层,對(duì)用戶也不會(huì)產(chǎn)生任何影響镰禾,因?yàn)樗麄內(nèi)栽谑褂门f數(shù)據(jù)存儲(chǔ)中的數(shù)據(jù)。如果數(shù)據(jù)和指標(biāo)均符合預(yù)期唱逢,您可以為部分用戶關(guān)閉 MySQL 的讀關(guān)開(kāi)吴侦,將使用 HBase 的數(shù)據(jù),并最終直到所有用戶均從 HBase 中讀取坞古。

最后妈倔,當(dāng)我們向所有用戶開(kāi)啟 HBase 讀取和寫(xiě)入操作后,應(yīng)該將所有舊數(shù)據(jù)從舊數(shù)據(jù)存儲(chǔ)遷移到新數(shù)據(jù)存儲(chǔ)(確保以冪等方式執(zhí)行此操作)來(lái)保證數(shù)據(jù)的整體完整性绸贡。

可見(jiàn),通過(guò)上述功能開(kāi)關(guān)漸進(jìn)式放量遷移的方式毅哗,不僅讓使得遷移可以無(wú)縫進(jìn)行(對(duì)用戶無(wú)感知)听怕,還有效保障的遷移的安全性。

3虑绵、收尾工作

最后一步尿瞭,我們需要確保關(guān)閉了舊數(shù)據(jù)庫(kù)(MySQL)的讀寫(xiě)開(kāi)關(guān),同時(shí)刪除代碼中對(duì)所有四個(gè)開(kāi)關(guān)的所有引用翅睛,使代碼中最終只剩下對(duì) HBase (新數(shù)據(jù)庫(kù))的讀/寫(xiě)声搁。再次部署上線后黑竞,便完成了整個(gè)數(shù)據(jù)庫(kù)的遷移工作。

在 FeatureProbe 開(kāi)關(guān)管理也很簡(jiǎn)單疏旨,由于以上四個(gè)開(kāi)關(guān)已經(jīng)完成了數(shù)據(jù)庫(kù)遷移的使命很魂,對(duì)于已經(jīng)過(guò)期、已完成工作的開(kāi)關(guān)都可以使用下線操作進(jìn)行管理檐涝。

FeatureProbe 就是一個(gè)高效的功能管理 (Feature management) 開(kāi)源服務(wù)遏匆,它提供了灰度放量、AB實(shí)驗(yàn)谁榜、實(shí)時(shí)配置變更等針對(duì)功能粒度的一系列管理能力幅聘。目前 FeatureProbe 使用 Apache 2.0 License 協(xié)議已經(jīng)完全開(kāi)源, 開(kāi)源地址:https://github.com/FeatureProbe/FeatureProbe

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窃植,一起剝皮案震驚了整個(gè)濱河市帝蒿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巷怜,老刑警劉巖葛超,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異丛版,居然都是意外死亡巩掺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門页畦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胖替,“玉大人,你說(shuō)我怎么就攤上這事豫缨《懒睿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵好芭,是天一觀的道長(zhǎng)燃箭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)舍败,這世上最難降的妖魔是什么招狸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮邻薯,結(jié)果婚禮上裙戏,老公的妹妹穿的比我還像新娘。我一直安慰自己厕诡,他們只是感情好累榜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著灵嫌,像睡著了一般壹罚。 火紅的嫁衣襯著肌膚如雪葛作。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天猖凛,我揣著相機(jī)與錄音赂蠢,去河邊找鬼。 笑死形病,一個(gè)胖子當(dāng)著我的面吹牛客年,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漠吻,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼量瓜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了途乃?” 一聲冷哼從身側(cè)響起绍傲,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耍共,沒(méi)想到半個(gè)月后烫饼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡试读,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年杠纵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钩骇。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡比藻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出倘屹,到底是詐尸還是另有隱情银亲,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布纽匙,位于F島的核電站务蝠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烛缔。R本人自食惡果不足惜馏段,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望践瓷。 院中可真熱鬧毅弧,春花似錦、人聲如沸当窗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)崖面。三九已至元咙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巫员,已是汗流浹背庶香。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留简识,地道東北人赶掖。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像七扰,于是被迫代替她去往敵國(guó)和親奢赂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容