歡迎光臨
每天分享高質量文章

阿裡巴巴資料庫分庫分表的最佳實踐

點擊▲關註 “資料和雲”   給公眾號標星置頂

更多精彩 第一時間直達

 

1.阿裡巴巴分佈式資料層發展和演變

業務資料從原來的單庫單表樣式變成了資料被拆分到多個資料庫,甚至多個表中,如果在資料訪問層做一下功能的封裝和管控,所有分庫分表的邏輯和資料的跨庫操作都交給應用的開發人員來實現,則對開發人員的要求變得相對高一點,稍有不慎,可能會對平臺的業務包括資料帶來較大的影響。

 

在2006年阿裡巴巴B2B團隊以開源方式研發了Cobar這一關係型資料的分佈式處理系統。該系統在很大程度上解決了最初使用Oracle資料庫因為儲存資料變得越來越大帶來的擴展性問題,並且為開發人員提供了一個使用相對簡單的用戶體驗,在當時Cobar平均每天處理近50億次的SQL操作。但隨著阿裡巴巴業務場景越來越複雜,Cobar平臺功能上的約束對滿足某些業務場景顯得力不從心,例如:

1)不支持跨庫情況下的連接、分頁、排序、子查詢操作。

2)SET陳述句執行會被忽略,處理事務和字符集設置除外。

3)分庫情況下,insert陳述句必須包含拆分欄位列名。

4)分庫情況下,update陳述句不能更新拆分欄位的值。

5)不支持SAVEPOINT操作。

6)使用JDBC時,不支持rewriteBatchedStatements=true引數設置(預設為false)。

7)使用JDBC時,不支持useServerPrepStmts=true引數設置(預設為false)。

8)使用JDBC時,BLOB、BINARY、VARBINARY欄位不能使用setBlob()或setBinaryStream()方法設置引數。

 

2008年阿裡巴巴內部基於淘寶業務發展的需要,在Cobar的基礎上重新研發了分佈式資料層框架TDDL(Taobao Distributed Data Layer,外號:頭都大了),針對分庫分表場景,提供了對各種業務場景的支持更加完善,開發人員體驗更加友好,管控能力大幅提升。

 

目前TDDL已經成為阿裡巴巴集團內部業務預設使用的分佈式資料層中間件,支撐著今天阿裡巴巴上千個應用,平均每天SQL呼叫超千億次。從架構角度(如圖5-3所示),TDDL沿襲了Cobar之前在應用和後端資料庫之間的定位,通過增加對SQL的解析實現了更為精準的路由控制,以及對跨庫join、統計等計算的支持,彌補了之前Cobar在功能上的約束和限制,成為一個完整支持SQL語法兼容的平臺。

圖5-3TDDL架構示意圖

 

三層資料源每層都按JDBC規範實現,使得對前端應用沒有任何代碼侵入。

Matrix層(TDataSource)實現分庫分表邏輯,底下持有多個GroupDs

實體。

Group層(TGroupDataSource)實現資料庫的主備/讀寫分離邏輯,底下持有多個AtomDs實體。

Atom層(TAtomDataSource)實現資料庫連接(ip、port、password、connec-

tionProperties)等信息的動態推送,持有原子的資料源。

 

通過TDDL實現一次來自應用的SQL請求,完整的交互流程(如圖5-4所示)中體現了各個服務組件所起到的作用。

圖5-4TDDL針對一次SQL請求完整處理流程

 

正是有了這樣的架構和設計,特別是增加了對SQL語意的解析,使得TDDL相比之前的Cobar在功能上提升了一個新的層級,對於Cobar不支持的跨庫資料聚合、子查詢、group by、order by等特性都有了很好的支持,從而成為在分庫分表技術業界被很多技術同仁認可的一套分佈式資料層框架,總結來說,TDDL提供了以下優點:

  • 資料庫主備和動態切換。

  • 帶權重的讀寫分離。

  • 單執行緒讀重試。

  • 集中式資料源信息管理和動態變更。

  • 支持MySQL和Oracle資料庫。

  • 基於JDBC規範,很容易擴展支持實現JDBC規範的資料源。

  • 無Server、client-jar形式存在,應用直連資料庫。

  • 讀寫次數,併發度流程控制,動態變更。

  • 可分析的日誌打印,日誌流控,動態變更。

 

隨著阿裡巴巴集團業務的多元化,特別是對於除電商領域以外業務的不斷擴展和併購,TDDL這種無Server的樣式對於故障的定位和對運行環境的要求(必須是阿裡巴巴內部服務環境),支持這些新興業務有了不少困難,所以在2014年,阿裡巴巴已經研發出新一代分佈式資料庫產品DRDS(Distributed Relational Database Service),該產品相比TDDL在業務場景的支持、故障的定位、運維管控等方面又有了一個全面的提升,今天DRDS已經成為阿裡雲上用於解決關係型資料庫線性擴展問題的標準雲產品,服務了幾百家阿裡巴巴集團外部的客戶。

 

2.資料盡可能平均拆分

不管是採用何種分庫分表框架或平臺,其核心的思路都是將原本儲存在單表中太大的資料進行拆分,將這些資料分散儲存到多個資料庫的多個表中,避免因為單表資料太大給資料的訪問帶來讀寫性能的問題。所以在分庫分表場景下,最重要的一個原則就是被拆分的資料盡可能的平均拆分到後端的資料庫中,如果拆分得不均勻,還會產生資料訪問熱點,同樣存在熱點資料因為增長過快而又面臨資料單表資料過大的問題。

 

而對於資料以什麼樣的維度進行拆分,大家看到很多場景中都是對業務資料的ID(大部分場景此ID是以自增的方式)進行哈希取模的方式將資料進行平均拆分,這個簡單的方式確實在很多場景下都是非常合適的拆分方法,但並不是在所有的場景中這樣拆分的方式都是最優選擇。也就是說資料如何拆分並沒有所謂的金科玉律,更多的是需要結合業務資料的結構和業務場景來決定。

 

下麵以大家最熟悉的電商訂單資料拆分為例,訂單是任何一個電商平臺中都會有的業務資料,每個淘寶或天貓用戶在平臺上提交訂單後都會在平臺後端生成訂單相關的資料,一般記錄一條訂單資料的資料庫表結構如圖5-5所示。

 

訂單資料主要由三張資料庫表組成,主訂單表對應的就是用戶的一個訂單,每提交一次都會生成一個主訂單表的資料。在有些情況下,用戶可能在一個訂單中選擇不同賣家的商品,而每個賣家又會按照該訂單中是自己提供的商品計算相關的商品優惠(比如滿88元免快遞費)以及安排相關的物流配送,所以會出現子訂單的概念,即一個主訂單會由多個子訂單組成,而真正對應到具體每個商品的訂單信息,則是儲存在訂單詳情表中。

圖5-5 訂單相關資料表結構示意

 

如果一個電商平臺的業務發展健康的話,訂單資料是比較容易出現因為單個資料庫表中的資料太大而造成性能的瓶頸,所以需要對它進行資料庫的拆分。此時從理論上對訂單拆分是可以由兩個維度進行的,一個維度是通過訂單ID(一般為自增ID)取模的方式,即以訂單ID為分庫分表鍵;一個是通過買家用戶ID的維度進行哈希取模,即以買家用戶ID為分庫分表鍵。

 

兩種方案做一下對比:

如果是按照訂單ID取模的方式,比如按64取模,則可以保證主訂單資料以及相關的子訂單、訂單詳情資料平均落入到後端的64個資料庫中,原則上很好地滿足了資料盡可能平均拆分的原則。

 

通過採用買家用戶ID哈希取模的方式,比如也是按64取模,技術上則也能保證訂單資料拆分到後端的64個資料庫中,但這裡就會出現一個業務場景中帶來的一個問題,就是如果有些賣家是交易量非常大的(這樣的群體不在少數),那這些賣家產生的訂單資料量(特別是訂單詳情表的資料量)會比其他賣家要多出不少,也就是會出現資料不平均的現象,最終導致這些賣家的訂單資料所在的資料庫會相對其他資料庫提早進入到資料歸檔(為了避免在線交易資料庫的資料的增大帶來資料庫性能問題,淘寶將3個月內的訂單資料儲存進在線交易資料庫中,超過3個月的訂單會歸檔到後端專門的歸檔資料庫)。

 

所以從對“資料盡可能平均拆分”這條原則來看,按照訂單ID取模的方式看起來是更能保證訂單資料進行平均拆分,但我們暫且不要這麼快下結論,讓我們繼續從下麵幾條原則和最佳實踐角度多思考不同的拆分維度帶來的優缺點。

 

3.儘量減少事務邊界

不管是TDDL平臺還是DRDS,採用分庫分表的方式將業務資料拆分後,如果每一條SQL陳述句中都能帶有分庫分表鍵,如圖5-6所示是以自增的訂單ID以8取模,將訂單平均分佈到8個資料庫的訂單表中,通過分佈式服務層在對於SQL解析後都能精準地將這條SQL陳述句推送到該資料所在的資料庫上執行,資料庫將執行的結果再傳回給分佈式服務層,分佈式服務層再將結果傳回給應用,整個資料庫訪問的過程跟之前的單機資料庫操作沒有任何差別。這個是在資料進行了分庫分表拆分後,SQL陳述句執行效率最高的方式。

圖5-6DRDS對帶分庫分表鍵的SQL請求處理

 

但不是所有的業務場景在進行資料庫訪問時每次都能帶分庫分表鍵的。比如在買家中心的界面中,要顯示買家test1過去三個月的訂單串列信息,因為該買家test1的訂單按訂單ID取模的方式分佈到了不同的資料庫中,此時SQL陳述句中就沒有了分庫分表鍵值,則出現瞭如圖5-7所示的情況,分佈式資料層會將獲取test1訂單的SQL陳述句推送到後端所有資料庫中執行,然後將後端資料庫傳回的結果在分佈式資料層進行聚合後再傳回給前端應用。

圖5-7DRDS對不帶分庫分表鍵的SQL請求進行全表掃描處理

 

此時就出現了我們所說的全表掃描。此時我們來解釋一下這裡“事務邊界”的定義,所謂的事務邊界即是指單個SQL陳述句在後端資料庫上同時執行的數量,上面示例中就是事務邊界大的典型示例,即一條SQL陳述句同時被推送到後端所有資料庫中運行。事務邊界的數量越大,會給系統帶來以下弊端:

系統的鎖衝突概率越高。如果事務邊界大的SQL請求比較多,在一次SQL請求處理過程中自然對於後端的資料庫操作的資料庫記錄改寫比較廣,當有多個類似的SQL請求並行執行時,則出現資料鎖造成的資源訪問互斥的概率會大大增加。

 

系統越難以擴展。如果有大量的SQL請求都是這樣全表掃描,或者從極端角度說明這個問題,如果每一次的SQL請求都需要全表掃描執行,你會發現整個平臺的資料庫連接數量是取決於後端單個資料庫的連接能力,也就意味著整個資料庫的能力是無法通過增加後端資料庫實體來擴展的。所以如果有大量的全表掃描的SQL請求對於系統的擴展能力會帶來不小的影響。

 

整體性能越低。對於性能,這裡想強調的是對系統整體性能的影響,而不是單次SQL的性能。應用發送獲取買家test1訂單串列SQL的請求(如圖5-8步驟①)時,分佈式資料層會並行的將這條SQL陳述句推送(如圖5-8步驟②)到後端8台資料庫上運行,因為訂單資料進行了平均的拆分,單個資料庫訂單表的資料量大小都使得資料庫處於最佳性能表現的狀態,所以意味著每一個資料庫傳回的計算結果都是在一個可期望的時間內(比如100毫秒),將結果傳回到分佈式資料層(如圖5-8步驟③),分佈式資料層將從各個資料庫傳回來的結果在記憶體中進行聚合或排序等操作(如圖5-8步驟④),最後傳回訂單串列給應用(如圖5-8步驟⑤)。

圖5-8DRDS對需全表掃描操作的SQL請求處理流程

 

整個SQL執行的過程包含了5個步驟,仔細看看,你會發現一次帶分庫分表鍵執行的SQL過程也會經歷這5個步驟,區別隻是在②③步驟是並行的方式同時跟多個後端資料庫進行交互,但在時間上帶來的影響幾乎是毫秒級的;而第④個步驟是可能造成差異的一個點,如果像示例中一個用戶的訂單信息可能最多幾千條,對於幾千條資料的記憶體聚合操作,處理時間也是毫秒級的,所以這樣一次全表掃描的操作,用戶的體驗是完全無感知的,跟訪問單機資料庫的體驗是沒有差異的。但如果在第④個步驟中確實遇到對大資料量(比如幾十萬、幾百萬條資料)的聚合、排序、分組等計算時,則會占用較大的記憶體和CPU計算資源,如果這樣型別的SQL請求比較頻繁的話,就會給分佈式資料層帶來較大的資源占用,從而導致整體分佈式服務的處理性能受到影響。

 

很多人對於全表掃描會有一些誤解,甚至認為出現全表掃描對於系統來說是完全不能接受的。其實全表掃描在真實的業務場景中很難完全避免(也可以做到完全避免,但會帶來其他方面的問題,後面會有說明),對於在分佈式資料層的記憶體中進行資料量不大的聚合這類的SQL請求,如果不是高併發同時請求的情況下,比如對訂單進行複雜的條件檢索,如圖5-9所示,就一定需要採用全表掃描的方式,將查詢陳述句同時推送到後端的資料庫中才能實現該場景的要求,但因為呼叫不會特別頻繁,而且計算的資料量不會太大,所以整體不會給資料庫整體性能帶來太大的影響。

圖5-9 訂單搜索是典型的多條件查詢場景

 

如果是高併發情況下同時請求的話,為了資料庫整體的擴展能力,則要考慮下麵描述的異構索引手段來避免這樣的情況發生。對於在記憶體中要進行大資料量聚合操作和計算的SQL請求,如果這類SQL的不是大量併發或頻繁呼叫的話,平臺本身的性能影響也不會太大,如果這類SQL請求有併發或頻繁訪問的要求,則要考慮採用其他的平臺來滿足這一類場景的要求,比如Hadoop這類做大資料量離線分析的產品,如果應用對請求的實時性要求比較高,則可採用如記憶體資料庫或HBase這類平臺,這一部分的內容不在本書中討論。

 

4.異構索引表儘量降低全表掃描頻率

還是基於訂單資料的分庫分表場景,按照訂單ID取模雖然很好地滿足了訂單資料均勻地儲存在後端資料庫中,但在買家查看自己訂單的業務場景中,就出現了全表掃描的情況,而且買家查看自己訂單的請求是非常頻繁的,必然給資料庫帶來擴展或性能的問題,有違“儘量減少事務邊界”這一原則。其實這類場景還有很多,比如賣家要查看與自己店鋪相關的訂單信息,同樣也會出現上述所說的大量進行全表掃描的SQL請求。

 

針對這類場景問題,最常用的是採用“異構索引表”的方式解決,即採用異步機制將原表內的每一次創建或更新,都換另一個維度儲存一份完整的資料表或索引表。本質上這是互聯網公司很多時候都採用的一個解決思路:“拿空間換時間”。

 

也就是應用在創建或更新一條按照訂單ID為分庫分表鍵的訂單資料時,也會再儲存一份按照買家ID為分庫分表鍵的訂單索引資料,如圖5-10所示,其結果就是同一買家的所有訂單索引表都儲存在同一資料庫中,這就是給訂單創建了異構索引表。

圖5-10 訂單異構索引表

 

這時再來看看買家test1在獲取訂單信息進行頁面展現時,應用對於資料庫的訪問流程就發生瞭如圖的5-11變化。

 

在有了訂單索引表後,應用首先會通過當前買家ID(以圖示中test1為例),首先到訂單索引表中搜索出test1的所有訂單索引表(步驟①),因為步驟②SQL請求中帶了以buyer_ID的分庫分表鍵,所以一次是效率最高的單庫訪問,獲取到了買家test1的所有訂單索引表串列並由DRDS傳回到了前端應用(步驟③和④),應用在拿到傳回的索引串列後,獲取到訂單的ID串列(1,5,8),在發送一次獲取真正訂單串列的請求(步驟⑤),同樣在步驟⑥的SQL陳述句的條件中帶了分庫分表鍵order_ID的串列值,所以DRDS可以精確地將此SQL請求發送到後端包含in串列值中訂單ID的資料庫,而不會出現全表掃描的情況,最終通過兩次訪問效率最高的SQL請求代替了之前需要進行全表掃描的問題。

圖5-11 基於訂單索引表實現買家訂單串列查看流程示意

 

這時你可能會指出,為什麼不是將訂單的完整資料按照買家ID維度進行一次分庫儲存,這樣就只需要進行一次按買家ID維度進行資料庫的訪問就獲取到訂單的信息?這是一個好問題,其實淘寶的訂單資料就是在異構索引表中全複製的,即訂單按照買家ID維度進行分庫分表的訂單索引表跟以訂單ID維度進行分庫分表的訂單表中的欄位完全一樣,這樣確實避免了多一次的資料庫訪問。但一般來說,應用可能會按照多個維度創建多個異構索引表,比如為了避免買家查看自己的訂單時頻繁進行全表掃描,實際中還會以買家ID的維度進行異構索引表的建立,所以採用這樣資料全複製的方法會帶來大量的資料冗餘,從而增加不少資料庫儲存成本。

 

另外,在某些場景中,在獲取主業務表的串列時,可能需要依賴此業務表所在資料庫的子業務表信息,比如訂單示例中的主、子訂單,因為是以訂單ID的維度進行了分庫分表,所以該訂單相關的子訂單、訂單明細表都會儲存在同一個資料庫中,如果我們僅僅是對主訂單信息做了資料全複製的異構儲存,還是通過一次對這張異構表的資料進行查詢獲取包含了子訂單信息的訂單串列時,就會出現跨庫join的問題,其對分佈式資料層帶來的不良影響其實跟之前所說的全表掃描是一樣的。所以我們還是建議採用僅僅做異構索引表,而不是資料全複製,同時採用兩次SQL請求的方式解決出現全表掃描的問題。

 

實現對資料的異步索引創建有多種實現方式,一種是從資料庫層採用資料複製的方式實現;另一種是如圖5-12所示在應用層實現,在這一層實現異構索引資料的創建,就必然會帶來分佈式事務的問題。

圖5-12 實現資料同步的流程圖

 

這裡給大家介紹的是在資料庫層實現異構索引的方式。本質上是一個基於MySQL的實時資料複製框架,可以通過圖形界面配置的方式就可以實現異構資料複製的需求。除了在同步異構索引資料的場景外,可以認為是一個MySQL的資料觸發器+分發管道。

 

資料從源資料庫向標的資料庫的過程中,可能需要對資料進行一些過濾和轉換,本身的結構分為抽取器(Extractor)、管道(Pipeline)、分發器(Applier),資料從抽取器流入管道,管道中有過濾器可以執行對資料的一些過濾的操作,然後再交由分發器寫入到標的,如圖5-12所示。

 

平臺通過抽取器(Extractor)獲取到訂單資料創建在MySQL資料庫中產生的binlog日誌(binlog日誌會記錄對資料發生或潛在發生更改的SQL陳述句,並以二進制的形式儲存在磁盤中),並轉換為event物件,用戶可通過jw自帶的過濾器(Filter)(比如欄位過濾、轉換等)或基於接口自定義開發的過濾器對event物件中的資料進行處理,最終通過分發器(Applier)將結果轉換為發送給DRDS的SQL陳述句,通過jw實現異構索引資料的過程如圖5-13所示。

 

雖然jw平臺在系統設計和提供的功能不算複雜,但其實但凡跟資料相關的平臺就不會簡單。這裡不會對jw核心的組件和機製做更詳細的介紹,只是將jw多年來能力演變後,目前提供的核心功能做一下介紹,為有志在該領域深耕細作的技術同仁多一些思路和借鑒。

圖5-13 採用jw平臺實現異構索引表流程示意

 

(1)多執行緒管道實現

在jw平臺應用的早期,資料的同步均是採用單執行緒管道任務樣式,即如

圖5-12中對binlog進行單執行緒的處理。隨著業務的發展,需要同步的資料量越來越大,單純的單執行緒管道任務已經成為系統的瓶頸,後來開發了對多執行緒管道任務的支持(如圖5-14所示)。

圖5-14 jw支持多執行緒管道資料同步

 

但多執行緒管道就會帶來資料同步的順序問題。在對binlog資料進行多執行緒並行處理後,就不能保證在源資料庫中執行的SQL陳述句在標的資料庫的順序一致,這樣在某些業務場景中一定會出現資料不一致性的問題。對於這個問題,目前jw中提供的解決思路是保證同一條記錄或針對同一分庫表發生的資料同步按照順序執行。

 

如果最後發送到分佈式資料層的SQL陳述句中沒有分庫鍵,則通過對“庫名+表名+主鍵值”哈希後對執行緒數取模,這樣就能讓同一條記錄的資料同步事件處理都會在同一執行緒中順序執行,保證了該記錄多次變更的順序性,但是不保證不同記錄間的順序。如果SQL陳述句中有分庫鍵,則通過“庫名+分庫鍵值”哈希後對執行緒數取模,效果是保證不同邏輯表針對相同分庫邏輯的記錄變化順序。

 

(2)資料的安全

凡是牽涉資料的操作,資料的安全一定是最重要的。如何保證在分佈式環境下同步任務效率最大化,同時保證服務的穩定和資料的安全,是很多此類平臺精益求精、力求突破的方向。

 

平臺穩定性保障。為了保證同步任務執行的效率最大化,同時互相不會因為資源會搶占或某些同步任務的異常對其他任務造成影響,在jw的系統設計中,支持多個服務節點作為任務執行的集群,通過統一的任務調度系統(Zookeeper集群),將任務分配到集群中的各節點並行執行。

 

為了保證任務間不會因為同步任務性能或異常造成互相的干擾,採用了每個同步任務都是獨立Java行程的方式運行,出現異常該任務自動終止。任務調度系統會定期輪詢任務串列,發現任務缺少立即搶占式啟動該任務。

 

心跳+報警。運行集群與ZooKeeper採用定時心跳的方式,將集群節點的運行狀態以及任務完成的位點(即目前同步任務處理binlog的進度信息)信息同步到Zookeeper上,如果心跳信息異常或位點時間落後過大則立即報警。在抽取器和分發器發生任何錯誤複製任務立即轉變成STANDBY狀態,集群中其他機器上的服務在感知後會立即將自己啟動,繼續執行前一複製任務。

 

MySQL主備切換。利用比對主備資料庫的狀態信息,通過以下順序,採用手工的方式處理MySQL出現主備切換時進行同步任務的恢復:

1)查看新主庫的當前位點Show master status,獲取到PA狀態。

2)查看老主庫拉去新主庫的位置Show slave status,獲取到PR狀態。

3)如果PR>PA,直接用新主庫的位點PA切換到新主庫上讀取。

 

如果希望通過自動化的方式,實現的思路則可利用binlog里的serverId和時間戳,發現dump的binlog中的serverId發生變化記錄變化時間戳,然後在給定的MySQL服務器中查找到有同樣變化的資料庫,根據探測到的serverId發生變化的時間戳進行回溯,在新的機器符合條件的位點進行dump。

 

MySQL異常掛掉。利用資料庫上binlog檔案修改時間,按照以下順序採取手工的方式進行整個檔案回溯:

1)在資料庫所在的服務器上找到服務掛掉的時間點。

2)到新的主機上查看找到服務掛掉時間點之前最近的binlog檔案。

3)從這個檔案的位點開始進行回溯。

 

如果希望通過自動化的方式自動進行恢復,可同樣借鑒MySQL主備切換中提到的自動化實現思路。

 

(3)友好的用戶自服務接入體驗

jw平臺是整個電商業務實現資料實時同步複製的統一平臺,負責來自上千個不同應用的需求,如果每一個應用的接入都需要平臺的技術人員給予入門的培訓和支持都是非常大的工作量,也會影響到前端應用的用戶體驗。所以提供一個用戶體驗友好,自帶常用功能的平臺,能針對大部分的業務需求可以讓應用方在界面上通過配置的方式就能實現,大大降低接入開發成本。

 

如圖5-15所示,jw平臺給應用方客戶提供了Web的配置界面,可讓用戶針對需要同步的資料源進行設置,並對資料同步的事件型別(增、刪、改)和是否進行分表以及分庫分表鍵列等進行設置。

 

jw平臺的資料庫分發器支持一些高級功能,如欄位過濾、欄位映射、action轉換等,如果自帶功能不滿足需求,可以上傳包含自己的業務邏輯的過濾代碼。這些功能的使用也提供了界面的方式,讓用戶對源資料庫表中的欄位如何映射到標的資料庫表進行設置(如圖5-16所示)。

 

圖5-15 jw支持界面配置不同資料源間的資料同步

圖5-16 jw提供的自服務體驗提升資料同步服務接入效率

 

正是有了這樣簡單易用的用戶體驗,使得jw平臺在應用的接入效率和用戶滿意度上都有非常不錯的表現。

 

(4)平臺管控和統計

在jw的平臺中,每天都運行著上千億次的資料同步和複製任務,必然需要對這些任務的執行有一個清晰的管控,甚至可以從中找出對業務資料變化的趨勢。實現的方法是定時輪詢Zookeeper集群中對應任務的節點進行監控,如圖5-17所示。目前提供以下三個方面監控:

心跳監控。

延遲堆積監控。

任務狀態、資料監控(TPS、異常)等。

圖5-17 jw平臺提供的資料同步監控

 

採用類似這樣的平臺實現資料異構索引的好處是,不需要在各個前端應用層的代碼中去實現,只需統一通過jw平臺實現。有了這樣專業的平臺來實現資料同步的效率、服務高可用性、任務管控、統計等,能提供更好的服務。但設計這樣的平臺確實需要掌握資料庫相關知識,以及任務調度、平臺管控等技術,甚至需要在各種複雜場景中逐步打磨和完善技術。所以如果有些企業還沒有這樣資料同步的專業平臺,通常會建議採用通過在應用層實現資料的異構索引,具體實現方式在6.3節中重點闡述。

 

5.將多條件頻繁查詢引入搜索引擎平臺

採用資料異構索引的方式在實戰中基本能解決和避免90%以上的跨join或全表掃描的情況,是在分佈式資料場景下,提升資料庫服務性能和處理吞吐能力的最有效技術手段。但在某些場景下,比如淘寶商品的搜索(如圖5-18)和高級搜索(如圖5-19),因為商品搜索幾乎是訪問淘寶用戶都會進行的操作,所以呼叫非常頻繁,如果採用SQL陳述句的方式在商品資料庫進行全表掃描的操作,則必然對資料庫的整體性能和資料庫連接資源帶來巨大的壓力。

 

圖5-18 淘寶網商品全文搜索

 

圖5-19 淘寶網商品高級搜索

 

所以面對此類場景,我們不建議採用資料庫的方式提供這樣的搜索服務,而是採用專業的搜索引擎平臺來行使這樣的職能,實現的架構如圖5-20所示。

圖5-20 全文搜索實現示意圖

 

阿裡巴巴有自身的主搜索平臺,該平臺承載了淘寶、天貓、一淘、1688、神馬搜索等搜索業務,其核心功能跟業界開源工具,如Iucene、Solr、ElasticSearch等搜索引擎類似,但在資料同步(從資料庫到搜索引擎)、索引創建演算法、查詢執行計劃、排序演算法等方面針對商品搜索這樣的場景做了相應的調整和功能增強。該搜索平臺目前已經以阿裡雲上OpenSearch產品的形態,給有此類搜索需求的客戶提供強大的搜索服務,更多關於該平臺詳細的資料可訪問開放搜索服務的官方網站:https://www.aliyun.com/product/opensearch。

 

6.簡單就是美

在真實的世界中,選擇的困難往往是因為充滿著各種誘惑,選擇A方案,有這些好處;而選擇B方案,也會有另外一些好處。

 

如果在“儘量減小事務邊界”與“資料盡可能平均拆分”兩個原則間發生了衝突,那麼請選擇“資料盡可能平均拆分”作為優先考慮原則,因為事務邊界的問題相對來說更好解決,無論是做全表掃描或做異構索引複製都是可以解決的。而寫入或單機容量如果出現不均衡,那麼處理起來難度就比較大。

 

儘管複雜的切分規則或資料的異構索引能夠給系統的性能和擴展性帶來顯著的收益,但其後面所帶來的系統運維複雜度上升也是不能忽視的一個結果。

 

如果為每一個存在跨join或全表掃描的場景都採用資料異構索引的方式,整個資料庫出現大量資料冗餘,資料一致性的保障也會帶來挑戰,同時資料庫間的業務邏輯關係也變得非常複雜,給資料庫運維帶來困難和風險,從而對資料庫運維人員的要求和依賴會非常高,所以從系統風險的角度考慮,以82法則,在實際中,我們僅針對那些在80%情況下訪問的那20%的場景進行如資料異構索引這樣的處理,達到這類場景的性能最優化,而對其他80%偶爾出現跨庫join、全表掃描的場景,採用最為簡單直接的方式往往是就最有效的方式。

轉載自:技術瑣話

    赞(0)

    分享創造快樂