国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

干貨 | 數據為王,攜程國際火車(chē)票的 ShardingSphe

發(fā)布時(shí)間:2021-08-26 11:17 來(lái)源:ITPUB博客 閱讀:0 作者: 欄目: Mysql 歡迎投稿:712375056

作者簡(jiǎn)介

 

瑞華,攜程高級后端開(kāi)發(fā)工程師,關(guān)注系統架構、分庫分表、微服務(wù)、高可用等。


一、前言

隨著(zhù)國際火車(chē)票業(yè)務(wù)的高速發(fā)展,訂單量快速增長(cháng),單數據瓶頸層面的問(wèn)題逐漸顯露,常規的數據庫優(yōu)化已無(wú)法達到期望的效果。同時(shí),原先的底層數據庫設計,也存在一些歷史遺留問(wèn)題,比如存在部分無(wú)用字段、表通過(guò)自增主鍵關(guān)聯(lián)和各個(gè)應用直連數據庫等問(wèn)題。

為此,經(jīng)過(guò)討論后,我們決定對訂單庫進(jìn)行分庫分表,同時(shí)對訂單表進(jìn)行重構,進(jìn)而從根本上解決這些問(wèn)題。

二、問(wèn)題挑戰

目標確定后,實(shí)踐起來(lái)可不輕松,出現了很多的問(wèn)題和挑戰。這里列舉一些典型問(wèn)題,大致可以分為兩大類(lèi):分庫分表通用問(wèn)題、具體業(yè)務(wù)關(guān)聯(lián)問(wèn)題。
分庫分表通用問(wèn)題

  • 如何切分,垂直分還是水平分?分片的鍵,如何選???
  • 如何根據鍵值路由到對應庫、對應表?
  • 采用什么中間件,代理方式還是中間件的方式?
  • 跨庫操作等問(wèn)題,如跨庫事務(wù)和跨庫關(guān)聯(lián)?
  • 數據擴容問(wèn)題,后續如何進(jìn)行擴容?

具體業(yè)務(wù)關(guān)聯(lián)問(wèn)題

  • 各個(gè)應用直連數據如何解決?
  • 如何進(jìn)行平滑過(guò)渡?
  • 歷史數據如何恰當遷移?

三、方案選型

3.1 如何切分

切分方式,一般分為垂直分庫、垂直分表、水平分庫和水平分表四種,如何選擇,一般是根據自己的業(yè)務(wù)需求決定。
我們的目標是要從根本上解決數據量大、單機性能問(wèn)題等問(wèn)題,垂直方式并不能滿(mǎn)足需求,所以我們選取了水平分庫+水平分表的切分方式。

3.2 分片鍵選取

一般是根據自己的實(shí)際業(yè)務(wù),來(lái)選擇字段來(lái)作為分片的鍵,同時(shí)可以結合考慮數據的熱點(diǎn)問(wèn)題 、分布問(wèn)題。比如訂單系統,不能根據國家字段進(jìn)行分片,否則可能會(huì )出現某些國家很多的訂單記錄,某些國家幾乎沒(méi)有訂單記錄,進(jìn)而數據分布不均。相對正確的方式,比如訂單類(lèi)系統,可以選擇訂單 ID;會(huì )員系統,可以選擇會(huì )員 ID。

3.3 如何路由

選定了分片的鍵之后,接下來(lái)需要探討的問(wèn)題,就是如何路由到具體的數據庫和具體的表。以分片鍵路由到具體某一個(gè)數據庫為例,常見(jiàn)的路由方式如下:

映射路由

映射路由,即新增一個(gè)庫,新建一個(gè)路由映射表,存儲分片鍵值和對應的庫之間的映射關(guān)系。比如,鍵值為 1001,映射到 db01 這個(gè)數據庫,如下圖所示:

映射方式,優(yōu)點(diǎn)是映射方式可任意調整,擴容簡(jiǎn)單,但是存在一個(gè)比較嚴重的不足,就是映射庫中的映射表的數據量異常巨大。我們本來(lái)的目標是要實(shí)現分庫分表的功能,可是現在,映射庫映射表相當于回到了分庫分表之前的狀態(tài)。所以,我們在實(shí)踐中,沒(méi)有采取這種方式。

分組路由

分組路由,即對分片的鍵值,進(jìn)行分組,每組對應到一個(gè)具體的數據庫。比如,鍵值為 1000 到 2000,則存儲到 db01 這個(gè)數據庫,如下圖所示:

分組方式,優(yōu)點(diǎn)是擴容簡(jiǎn)單,實(shí)現簡(jiǎn)單,但是也存在一個(gè)比較嚴重的不足,是數據分布熱點(diǎn)問(wèn)題,比如在某一個(gè)時(shí)間內,分片鍵值為 2001,則在將來(lái)一段時(shí)間內,所有的數據流量,全部打到某一個(gè)庫(db02)。這個(gè)問(wèn)題,在互聯(lián)網(wǎng)環(huán)境下,也比較嚴重,比如在一些促銷(xiāo)活動(dòng)中,訂單量會(huì )有一個(gè)明顯的飆升,這時(shí)候各個(gè)數據庫不能達到分攤流量的效果,只有一個(gè)庫在接收流量,會(huì )回到分庫分表之前的狀態(tài)。所以,我們也沒(méi)有采取這種方式。

哈希路由

哈希路由,即對分片的鍵值,進(jìn)行哈希,然后根據哈希結果,對應到一個(gè)具體的數據庫。比如,鍵值為 1000,對其取哈希的結果為 01,則存儲到 db01 這個(gè)數據庫,如下圖所示:

哈希方式,優(yōu)點(diǎn)是分布均勻,無(wú)熱點(diǎn)問(wèn)題,但是反過(guò)來(lái),數據擴容比較麻煩。因為在擴容過(guò)程中,需要調整哈希函數,隨之帶出一個(gè)數據遷移問(wèn)題?;ヂ?lián)網(wǎng)環(huán)境下,遷移過(guò)程中往往不能進(jìn)行停服,所以就需要類(lèi)似多庫雙寫(xiě)等方式進(jìn)行過(guò)渡,比較麻煩。所以,在實(shí)踐中也沒(méi)有采取這種方式。

分組哈希路由

分組哈希路由,即對分片的鍵值,先進(jìn)行分組,后再進(jìn)行哈希。如下圖所示:

在實(shí)踐中,我們結合了前面的幾種方式,借鑒了他們的優(yōu)點(diǎn)不足,而采用了此種方式。因為分組方式,能很方便的進(jìn)行擴容,解決了數據擴容問(wèn)題;哈希方式,能解決分布相對均勻,無(wú)單點(diǎn)數據庫熱點(diǎn)問(wèn)題。

3.4 技術(shù)中間件

分庫分表的中間件選取,在行業(yè)內的方案還是比較多的,公司也有自己的實(shí)現。根據實(shí)現方式的不同,可以分為代理和非代理方式,下面列舉了一些業(yè)界常見(jiàn)的中間件,如下表(截至于 2021-04-08):

我們?yōu)槭裁醋罱K選擇了 ShardingSphere 呢?主要從這幾個(gè)因素考慮:

技術(shù)環(huán)境

  • 我們團隊是 Java 體系下的,對 Java 中間件有一些偏愛(ài)
  • 更偏向于輕量級組件,可以深入研究的組件
  • 可能會(huì )需要一些個(gè)性定制化

專(zhuān)業(yè)程度

  • 取決于中間件由哪個(gè)團隊進(jìn)行維護,是否是名師打造,是否是行業(yè)標桿
  • 更新迭代頻率,最好是更新相對頻繁,維護較積極的
  • 流行度問(wèn)題,偏向于流行度廣、社區活躍的中間件
  • 性能問(wèn)題,性能能滿(mǎn)足我們的要求

使用成本

  • 學(xué)習成本、入門(mén)成本和定制改造成本
  • 弱浸入性,對業(yè)務(wù)能較少浸入
  • 現有技術(shù)棧下的遷移成本,我們當前技術(shù)棧是 SSM 體系下

運維成本

  • 高可用、高穩定性
  • 減少硬件資源,不希望再單獨引入一個(gè)代理中間件,還要考慮運維成本
  • 豐富的埋點(diǎn)、完善的監控

四、業(yè)務(wù)實(shí)踐

在業(yè)務(wù)實(shí)踐中,我們經(jīng)歷了從新庫新表的設計,分庫分表自建代理、服務(wù)收口、上游訂單應用遷移,歷史數據遷移等過(guò)程。

4.1 新表模型

為了建立分庫分表下的關(guān)聯(lián)關(guān)系,和更加合理有效的結構,我們新申請了訂單分庫分表的幾個(gè)庫,設計了一套全新的表結構。表名以年份結尾、規范化表字段、適當增刪了部分字段、不使用自增主鍵關(guān)聯(lián),采用業(yè)務(wù)唯一鍵進(jìn)行關(guān)聯(lián)等。
表結構示例如下圖:

4.2 服務(wù)收口

自建了一個(gè)分庫分表數據庫的服務(wù)代理 Dal-Sharding。每一個(gè)需要操作訂單庫的服務(wù),都要通過(guò)代理服務(wù)進(jìn)行操作數據庫,達到服務(wù)的一個(gè)收口效果。同時(shí),屏蔽了分庫分表的復雜性,規范數據庫的基本增刪改查方法。

4.3 平滑過(guò)渡

應用遷移過(guò)程中,為了保證應用的平滑過(guò)渡,我們新增了一些同步邏輯,來(lái)保證應用的順利遷移,在應用遷移前后,對應用沒(méi)有任何影響。未遷移的應用,可以讀取到遷移后應用寫(xiě)入的訂單數據;遷移后的應用,能讀取到未遷移應用寫(xiě)入的訂單數據。同時(shí),統一實(shí)現了此邏輯,減少各個(gè)應用的遷移成本。

新老庫雙讀
顧名思義,就是在讀取的時(shí)候,兩個(gè)庫可能都要進(jìn)行讀取,即優(yōu)先讀取新庫,如果能讀到記錄,直接返回;否則,再次讀取老庫記錄,并返回結果。
雙讀的基本過(guò)程如下:

新老庫雙讀,保證了應用遷移過(guò)程中讀取的低成本,上游應用不需要關(guān)心數據來(lái)源于新的庫還是老的庫,只要關(guān)心數據的讀取即可,減少了切換新庫和分庫分表的邏輯,極大的減少了遷移的工作量。
實(shí)踐過(guò)程中,我們通過(guò)切面實(shí)現雙讀邏輯,將雙讀邏輯放入到切面中進(jìn)行,減小新庫的讀取邏輯的侵入,方便后面實(shí)現對雙讀邏輯的移除調整。
同時(shí),新增一些配置,比如可以控制到哪些表需要進(jìn)行雙讀,哪些表不需要雙讀等。

新老庫雙寫(xiě)
新老庫雙寫(xiě),就是在寫(xiě)入新庫成功后,異步寫(xiě)入到老庫中。雙寫(xiě)使得新老庫都同時(shí)存在這些訂單數據,尚未遷移通過(guò)代理服務(wù)操作數據庫的應用得以正常的運作。
雙寫(xiě)的基本過(guò)程如下:


雙寫(xiě)其實(shí)有較多的方案,比如基于數據庫的日志,通過(guò)監聽(tīng)解析數據庫日志實(shí)現同步;也可以通過(guò)切面,實(shí)現雙寫(xiě);還可以通過(guò)定時(shí)任務(wù)進(jìn)行同步;另外,結合到我們自己的訂單業(yè)務(wù),我們還可以通過(guò)訂單事件(比如創(chuàng )單成功、出票成功、退票成功等),進(jìn)行雙寫(xiě),同步數據到老庫中。
目前,我們經(jīng)過(guò)考慮,沒(méi)有通過(guò)數據庫日志來(lái)實(shí)現,因為這樣相當于把邏輯下沉到了數據庫層面,從實(shí)現上不夠靈活,同時(shí),可能還會(huì )涉及到一些權限、排期等問(wèn)題。實(shí)踐中,我們采取其他三種方式,互補形式,進(jìn)行雙寫(xiě)。異步切面雙寫(xiě),保證了最大的時(shí)效性;訂單事件,保證了核心節點(diǎn)的一致性;定時(shí)任務(wù),保證了最終的一致性。
跟雙讀一樣,我們也支持配置控制到哪些表需要進(jìn)行雙寫(xiě),那些表不需要雙寫(xiě)等。

過(guò)渡遷移
有了前面的雙讀雙寫(xiě)作為基礎,遷移相對容易實(shí)行,我們采取逐個(gè)遷移的方式,比如,按照服務(wù)、按照渠道和按照供應進(jìn)行遷移,將遷移工作進(jìn)行拆解,減少影響面,追求穩健。一般分為三步走方式:
1)第一階段,先在新對接的供應商中進(jìn)行遷移新庫,因為新上線(xiàn)的供應商,訂單量最少,同時(shí)哪怕出現了問(wèn)題,不至于影響到之前的業(yè)務(wù)。
2)再次遷移量比較少的線(xiàn)上業(yè)務(wù),此類(lèi)訂單,有一些量,但是追求穩定,不能因為切換新庫而產(chǎn)生影響。所以,將此類(lèi)業(yè)務(wù)放到了第二階段中進(jìn)行。
3)最后一步是,將量較大的業(yè)務(wù),逐漸遷移到新庫中,此類(lèi)業(yè)務(wù),需要在在有前面的保證后,方能進(jìn)行遷移,保證訂單的正常進(jìn)行。

4.4 數據遷移

數據遷移,即將數據,從老庫遷移到新庫,是新老庫切換的一個(gè)必經(jīng)過(guò)程。遷移的常規思路,一般是每個(gè)表一個(gè)個(gè)進(jìn)行遷移,結合業(yè)務(wù),我們沒(méi)有采取此做法,而是從訂單維度進(jìn)行遷移。
舉個(gè)例子:假如訂單庫有 Order 表、OrderStation 表、OrderFare 表三個(gè)表,我們沒(méi)有采取一個(gè)一個(gè)表分別進(jìn)行遷移,而是根據訂單號,以每一個(gè)訂單的信息,進(jìn)行同步。
大致過(guò)程如下:
1)開(kāi)啟一個(gè)定時(shí)任務(wù),查詢(xún)訂單列表,取得訂單號等基本訂單信息。
2)根據這個(gè)訂單號,去分別查詢(xún)訂單的其他信息,取得一個(gè)完整的訂單信息。
3)校驗訂單是否已經(jīng)完成同步,之前完成同步了則直接跳過(guò),否則繼續執行下一個(gè)訂單號。
4)將老庫的完整的訂單信息,映射成新庫的對應的模型。
5)將新的訂單信息,同步寫(xiě)入到新庫各個(gè)表中。
6)繼續執行下一個(gè)訂單號,直到所有的訂單號都完全同步結束。

4.5 完成效果

訂單庫經(jīng)過(guò)一個(gè)全新的重構,目前已經(jīng)在線(xiàn)上穩定運行,效果顯著(zhù),達到了我們想要的效果。

  • 服務(wù)收口,將分庫分表邏輯,收口到了一個(gè)服務(wù)中;
  • 接口統一管理,統一對敏感字段進(jìn)行加密;
  • 功能靈活,提供豐富的功能,支持定制化;
  • 分庫分表路由透明,且基于主流技術(shù),易于上手;
  • 完善的監控,支持到表維度的監控;


五、 常見(jiàn)問(wèn)題總結

5.1 分庫分表典型問(wèn)題

問(wèn)題1:如何進(jìn)行跨庫操作,關(guān)聯(lián)查詢(xún),跨庫事務(wù)?

回答:對于跨庫操作,在訂單主流程應用中,我們目前是禁止了比如跨庫查詢(xún)、跨庫事務(wù)等操作的。對于跨庫事務(wù),因為根據訂單號、創(chuàng )建年份路由,都是會(huì )路由到同一個(gè)數據庫中,也不會(huì )存在跨庫事務(wù)。同樣對于跨庫關(guān)聯(lián)查詢(xún),也不會(huì )存在,往往都是根據訂單來(lái)進(jìn)行查詢(xún)。同時(shí),也可以適當進(jìn)行冗余,比如存儲車(chē)站編碼的同時(shí),多存儲一個(gè)車(chē)站名稱(chēng)字段。

問(wèn)題2:如何進(jìn)行分頁(yè)查詢(xún)?

回答:目前在訂單主流程應用中的分頁(yè)查詢(xún),我們直接采用了 Sharding-JDBC 提供的最原始的分頁(yè)方式,直接按照正常的分頁(yè) SQL,來(lái)進(jìn)行查詢(xún)分頁(yè)即可。理由:主流程訂單服務(wù),比如出票系統,往往都是查詢(xún)前面幾頁(yè)的訂單,直接查詢(xún)即可,不會(huì )存在很深的翻頁(yè)。當然,對于要求較高的分頁(yè)查詢(xún),可以去實(shí)現二次查詢(xún),來(lái)實(shí)現更加高效的分頁(yè)查詢(xún)。

問(wèn)題3:如何支持很復雜的統計查詢(xún)?
回答:專(zhuān)門(mén)增加了一個(gè)寬表,來(lái)滿(mǎn)足那些很復雜查詢(xún)的需求,將常用的查詢(xún)信息,全部落到此表中,進(jìn)而可以快速得到這些復雜查詢(xún)的結果。

5.2 API 方法問(wèn)題

問(wèn)題:服務(wù)收口后,如何滿(mǎn)足業(yè)務(wù)各種不同的查詢(xún)條件?
回答:我們的 API 方法,相對固定,一般查詢(xún)類(lèi)只有兩個(gè)方法,根據訂單號查詢(xún),和根據 Condition 查詢(xún)條件進(jìn)行查詢(xún)。對于各種不同的查詢(xún)條件,則通過(guò)新增 Condition 的字段屬性來(lái)實(shí)現,而不會(huì )新增各種查詢(xún)方法。

5.3 均勻問(wèn)題

問(wèn)題:在不同 group 中,數據會(huì )存在分布不均勻,存在熱點(diǎn)問(wèn)題?
回答:是的,比如運行 5 年后,我們拓展成了 3 個(gè) group,每一個(gè) group 中存在 3 個(gè)庫,那么此時(shí),讀寫(xiě)最多的應該是第三個(gè) group。不過(guò)這種分布不均勻問(wèn)題和熱點(diǎn)問(wèn)題,是可接受的,相當于前面的兩個(gè) group,可以作為歷史歸檔 group,目前主要使用的 group 為第三個(gè) group。
隨著(zhù)業(yè)務(wù)的發(fā)展,你可以進(jìn)行調配,比如業(yè)務(wù)發(fā)展迅速,那么相對合理的分配,往往不會(huì )是每個(gè) group 是 3 個(gè)庫,更可能是應該是,越往后 group 內的庫越多。同時(shí),因為每個(gè) group 內是存在多個(gè)庫,與之前的某一個(gè)庫的熱點(diǎn)問(wèn)題是存在本質(zhì)差別,而不用擔心單數據庫瓶頸問(wèn)題,可以通過(guò)加庫來(lái)實(shí)現擴展。

5.4 Group 內路由問(wèn)題

問(wèn)題:對于僅根據訂單號查詢(xún),在 group 內的路由過(guò)程是讀取 group 內所有的表嗎?
回答:根據目前的設計,是的。目前是按年份分組,訂單號不會(huì )存儲其他信息,采用攜程統一方式生成,也就是如果根據訂單號查詢(xún),我們并不知道是存在于哪個(gè)表,則需要查詢(xún) group 內所有的表。對于此類(lèi)問(wèn)題,通常推薦做法是,可以適當增加因子,在訂單號中,存儲創(chuàng )建年份信息,這樣就可以知道對應那個(gè)表了;也可以年份適當進(jìn)行延伸,比如每 5 年一次分表,那么這樣調整后,一個(gè) group 內的表應該相對很少,可以極大加快查詢(xún)效能。

5.5 異步雙寫(xiě)問(wèn)題

問(wèn)題:為什么雙寫(xiě)過(guò)程,采用了多種方式結合的方式?

回答:首先,切面方式,能最大限度滿(mǎn)足訂單同步的時(shí)效性。但是,在實(shí)踐過(guò)程中,我們發(fā)現,異步切面雙寫(xiě),會(huì )存在多線(xiàn)程并發(fā)問(wèn)題。因為在老庫中,表的關(guān)聯(lián)關(guān)系依賴(lài)于數據庫的自增 ID,依賴(lài)于表的插入順序,會(huì )存在關(guān)聯(lián)失敗的情況。所以,單純依靠切面同步還不夠,還需要更加穩健的方式,即定時(shí)任務(wù)(訂單事件是不可靠消息事件,即可能會(huì )存在丟失情況)的方式,來(lái)保證數據庫的一致性。

關(guān)于作者
我們是攜程火車(chē)票研發(fā)團隊,負責火車(chē)票業(yè)務(wù)的開(kāi)發(fā)以及創(chuàng )新?;疖?chē)票研發(fā)在多種交通線(xiàn)路聯(lián)程聯(lián)運算法、多種交通工具一站式預定、高并發(fā)方向不斷地深入探索和創(chuàng )新,持續優(yōu)化用戶(hù)體驗,提高效率,致力于為全球人民買(mǎi)全球火車(chē)票。


歡迎掃碼關(guān)注我們

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

国产在线高清视频无码| 中文亚洲欧美日韩无线码| 麻豆果冻传媒精品| 白袜篮球体育生飞机Gay视频| 欧美人与动牲交A精品| 国产成人午夜福利免费无码R|