天天看點

Lindorm全量覆寫Bulkload——這可能是新老資料覆寫問題的最優解背景目前痛點我們的方案總結

背景

在大資料場景下,我們常常會在傳統的OLAP産品中進行視圖預計算、資料挖掘、模型訓練等過程,生成大量标簽、緯度資料。這些結果資料需要向實時的線上業務提供低rt的查詢服務,目前通用的做法是将這些結果資料批量導入到Hbase、Cassandra、Lindorm這些産品中做Serving層加速,這裡的批量導入過程在大資料體系内是非常常見的。

很多場景中,比如名單表,營銷活動表,人群标簽表重刷等,需要用最新計算的資料覆寫掉全部的老資料,此時業務會對批量導入提出全量覆寫的需求。舉個例子,假如使用者a的一行記錄有c1 = 1,c2 = 2,c3 = 3三個資料,導入c1 = 5, c3 = 6,希望c1和c3被更新,同時c2 = 2也被覆寫不再可見。

一般來說,業務對全量覆寫的批量導入過程常常會有以下要求:

1. 全量替換

新資料能夠自動覆寫掉所有老的資料。

2. 資料一緻性

新導入的一批資料盡可能同時可見,不一緻的中間狀态過長可能會有業務影響。一批資料導入最好具有原子

性,要麼一起成功,要麼一起復原成老的資料,如果任務失敗,髒資料進入到線上系統可能産生嚴重的後

果。

3. 資料恢複

如果上遊出現計算錯誤,希望可以快速回退到全量覆寫之前,甚至幾個版本之前的資料,作為系統的兜底能

力。

4. 速度

導入的速度要盡可能快,導入的速度直接決定了線上服務的效果和體驗。

5. 穩定

導入的大量資料,覆寫老資料的同時,不能影響線上實時服務的穩定性。

目前痛點

目前有很多優秀的産品可以做資料的批量導入導出,但是在全量覆寫場景下,依然有很多痛點無法得到很好的解決:

1. 全量覆寫實作困難

覆寫掉老的資料一般有2種選擇:

  • truncate 表

    最直覺的,導入之前先調用類似truncate的接口清空線上表,然後再開始導入,可以達到要求的效果,導入

    ODPS時就有這樣的配置。但是問題也很明顯,清空表之後,線上服務無資料,線上服務都無法接受。

  • AB表切換

    複雜一點的,使用者側控制AB表的切換,導入時寫B表,用業務層邏輯控制新老資料表的切換。這裡會大大增加業

    務邏輯的複雜度,對上層侵入很多,在有些系統中,AB表的改造方案幾乎不可行。在業務層控制表切換,切換的

    一緻性和容災能力也很難保證保證,會增加更多不穩定因素,降低系統整體的可用性。

2. 資料一緻性差

以DataX(一款阿裡研發的非常流行的資料同步産品)為例,很多DataX的插件都是逐行寫入,逐行可見,整個任務持續的過程,長時間處于新老資料不一緻的中間狀态,任務完成後,全部資料才完整可見。而且無原子性保障,逐行寫入的資料直接進入線上系統,如果任務失敗,髒資料無法復原。

3. 資料無法快速恢複

普通的導入模式,資料進入系統後,曆史資料被覆寫掉就無法再追回,一旦上遊計算錯誤,隻能重新導入覆寫,有些系統的邏輯下,甚至需要重跑完整的上遊鍊路,錯誤的恢複速度基本需要數小時甚至天級别。

速度較慢,直寫需要走完整的寫入流程,占用線上系統寫入吞吐,速度取決于線上系統的資源。

5. 穩定性

對線上系統穩定性有負面影響,批量導入如果速度過快,會有打爆線上系統的危險。被覆寫的老資料需要額外的compaction操作才能消化,這些都會帶來額外的穩定性風險。

我們的方案

鋪墊了這麼多(why應該說清楚了),我們來看一下how的問題,我們的方式是如何解決上面這些痛點的呢?下文會涉及到一些Lindorm内部的原理和細節,感興趣的同學歡迎交流。

1. 寫入方式

首先與其他方案使用資料庫系統的寫入接口導入不同,本方案使用Bulkload的方式進行寫入。Bulkload導入即跳過正常接口的RPC,MVCC,WAL等過程,直接對原資料集進行編碼壓縮生成底層檔案,然後全部的檔案一起旁路加載到線上資料庫系統中。

這樣的方式寫傳入連結路簡單直接,速度快一個數量級。并且在離線叢集進行編碼壓縮等消耗cpu的操作,旁路加載檔案,對線上叢集的服務節點幾乎無影響,可以最大程度保障海量資料流入場景下的線上系統穩定性

Lindorm全量覆寫Bulkload——這可能是新老資料覆寫問題的最優解背景目前痛點我們的方案總結

2. 全量覆寫的實作

在這種寫入方式下,我們可以通過資料庫系統的表重定向功能,實作全量替換操作。資料導入過程寫入一個全新的 表,寫入完成後進行切換操作。可以簡單了解成一個更強大的、native的AB表切換功能。

2.1 依賴表重定向的全量覆寫導入過程

Lindorm全量覆寫Bulkload——這可能是新老資料覆寫問題的最優解背景目前痛點我們的方案總結

如圖所示,依賴表重定向的全量替換導入過程如下:

a. bulkload導入過程中建立一個新的使用者不可見表版本v3,導入過程依賴Bulkload的特性,對目前服務的版

本v2不造城任何影響。

b. v3版本寫完之後,調用表的原資料接口,可以在非常短的時間内,将通路v2的通路,原子性的切換到新的v3版

c. 寫入完畢後可以異步的選擇清理曆史版本,并且如果新版本的表出現問題(如資料錯誤),支援回退到曆史版

本。

為了達到上述的全量替換方案,資料庫系統的表重定向能力是關鍵,是以本方案設計了一種資料庫表重定向能力的實作。

2.2 核心概念

實體表:指向一張邏輯表下的一個實體實表

邏輯表名:指向一個邏輯的主表,可能包含多個實體表

實體表的狀态機:

○ active:目前生效的實體表,唯一,一定存在,ddl/dml都會對此實體生效
○ building:目前正在建構資料的實體表,新create的實體表具有此狀态。
○ archived:已回檔的執行個體實體表,将building狀态的實體表至為active時,之前的active實體會被 置為歸檔狀态。歸檔狀态的實體表可以随時被切換為active。
○ disabled:已禁用,準備删除的實體表。隻有此狀态的實體表可以被删除           
Lindorm全量覆寫Bulkload——這可能是新老資料覆寫問題的最優解背景目前痛點我們的方案總結

說明:

• building -> active是單向的

• 建立的實體預設是building狀态,完成初始資料建構之後,顯式切換為active。過去的active實體自動變成archived

• archived實體可随時切換為active,以啟用曆史版本

• archived實體也可以切換為building,以對曆史版本進行資料建構(如資料訂正場景,但不推薦)

• building實體如果不想要了,可以直接archive,然後offline,再删除(3步操作)

• 存量表在建立第一個實體表時,即開啟此功能

• active實體一定存在,且保證唯一,但其他狀态的實體可以不存在,或者有多個

2.3 支援的重定向切換模式

模式 限制 優缺點
強一緻切換 對所有的業務client來說,要麼通路(讀寫)老實體,要麼通路新實體 切換過程中,存在不可通路的時間視窗。表越大,叢集規模越大,視窗期越長,秒級
最終一緻切換 讀寫都不做任何保證,都可能會同時通路到新老實體的資料。同一個client也會如此 業務對切換操作幾乎無感覺(讀操作因切換新表,緩存命中率低,可能會有RT升高的問題)

總結

按照前文中對比的次元,這個方案可以達到的效果:

  1. 全量覆寫

    表重定向到新表之後,全量覆寫功能自然實作,無需任何删除操作。舊的資料在舊的實體表中,可以異步的直接全表删除,不需要額外付出一次LSM tree結構的compaction操作。

  2. 一緻性

    有強一緻和最終一緻兩種可選的一緻性政策:強一緻以秒級的禁讀寫代價,可以保證新老資料無交叉的強一緻切換;最終一緻在使用者無感的情況下可以最終保證全部切換成新資料,并且新老資料交叉的中間過程通常隻在秒級,對比普通模式整個任務過程都不一緻,有本質差別。新資料都在新版本的表中,表重定向切換操作有原子保障,且支援失敗復原,可以確定無髒資料進入線上系統。

  3. 資料恢複

    支援秒級一鍵回切曆史版本,保留的曆史版本數量也可以按需配置,真正成為使用者資料的“後悔藥”。

  4. 速度

    具備Bulkload的優勢,鍊路短,速度快一個數量級,這一點Lindorm Bulkload的老使用者們應該都有體會了。

  5. 穩定性

    具備旁路導入的優勢,離線叢集生産資料檔案,不占用線上叢集資源,幾乎無影響。且老資料無需compaction消化,大幅節約系統資源開銷。

該功能目前已經正式釋出,已有不少業務同學正在測試、上線中,歡迎使用~