離線計算中的冪等和DataWorks中的相關事項

離線計算中的冪等和DataWorks中的相關事項

來自專欄 阿里大數據玩家

摘要: 冪等這個詞在軟體研發中經常被提到。比如消息發送時不應該同時給同個用戶推送多次相同的消息,針對同一筆交易的付款也不應該在重試過程中扣多次錢。曾見過一個案例,有個對於一個單據的確認模塊沒有考慮到冪等性,導致對應的單據有兩條確認記錄。

原文:click.aliyun.com/m/4250

概念

冪等這個詞在軟體研發中經常被提到。比如消息發送時不應該同時給同個用戶推送多次相同的消息,針對同一筆交易的付款也不應該在重試過程中扣多次錢。曾見過一個案例,有個對於一個單據的確認模塊沒有考慮到冪等性,導致對應的單據有兩條確認記錄。其實冪等這個詞是個數學的概念,表示這個操作執行多次的結果和執行一次是完全一樣的。嚴格的定義這裡不展開討論,有興趣的可以到網上搜一下,會有很多介紹。通俗一些說,冪等表示這個操作可以多次重跑,不用擔心重跑後到結果會亂掉。就賦值而言,i=1就是個冪等到操作,無論做多少次賦值,只要有做成功一次,i的值就是1。而i++就不是一個冪等的操作。如果多次執行這個操作,i的值會不斷增加1。

從前面的例子也可以看出,冪等的優勢是可以屏蔽重試帶來的問題。在分散式的環境里,一般會通過消息中間件、非同步調用等方式實現服務之間的解耦。在這過程中,如出現系統異常狀況下的狀態不明確的情況,一般會進行重試。如果應用不滿足冪等的要求,則就會出現錯誤的結果。

離線計算與冪等

離線計算里的一個作業經常是非常重的,跑一個作業要較多時間。而且由於其特性,經常是凌晨開始計算,在OLTP業務調用量上來以前需要產出結果。如果發現問題,經常沒有太多的時間留給技術人員去詳細定位問題的原因,然後清理臟數據後重新進行計算。這時候我們需要計算能夠進行任意次的重跑,也就是說計算需要滿足冪等性。對於一個滿足冪等性要求的作業,出現問題的時候,我們可以首先先重跑一下作業,以期能儘快恢復業務,後續再根據之前的日誌慢慢定位問題。下面我們以MaxCompute+ DataWorks為例,從不同的角度里討論離線計算的典型場景——離線數倉,看看都有哪些地方需要做到冪等以及如何做到。

計算

目前的離線計算,出於開發的效率考慮,一般都會考慮使用SQL進行代碼開發。SQL里包含DDL和DML兩種語句。除了SQL,計算引擎一般還支持MapReduce、Graph等計算模型。

DDL

DDL語法可以通過語句里的if exists/if not exists來確保冪等性。比如創建表可以用create table if not exists xxx,刪除表可以通過drop table if exists xxx來保證不報錯而且可以重複執行。當然創建表也可以先刪除後再創建來事先冪等性。誠然,如果是建表這種「一次性」的操作可以在上線的時候手工做好,但是日常的分區創建/刪除等操作就需要通過寫進代碼里,通過if exists/if not exists來保證可以重試。

DML

DML對數據有影響的是Insert操作。目前Insert有兩種模式:Insert into和Insert overwrite。其中Insert into是把數據追加到原來的數據里,而Insert overwrite是把以前的數據直接覆蓋。所以可以清楚得看到,Insert into是不滿足冪等性要求的,而Insert overwrite是滿足的。如果使用Dataworks的SQL節點跑一個Insert into的作業,會有提示

我也曾去了解一些使用Insert into的用戶,要使用這種數據更新方式的原因,除去數據訂正,發現一般都是針對一些不會變化的數據(比如網站的日誌、每天的統計結果等)每天需要追加到表裡。其實這種更好的方法是創建一個分區表,把每天需要Insert into的數據改成Insert overwrite到每天的一個不同分區里。

MapReduce

MapReduce默認就是使用覆蓋寫入的模式的。如果確實有需要追加寫入,可以使用com.aliyun.odps.mapred.conf.JobConfsetOutputOverwrite(boolean isOverwrite)來實現。

如果需要改成冪等的,可以使用前面SQL里提到的,把數據寫入特定的分區里來實現。

ETL

ETL我們暫時不考慮數據清洗(一般數據清洗是通過計算來實現的),而這隻討論數據的同步。在Dataworks里,數據的同步通過數據集成模塊來實現。在數倉中,數據同步包括數據導入到數倉和數據從數倉中導出兩種場景。

數據導入的場景要實現冪等性比較容易。只需要設置導入的MaxCompute表的清洗規則為「寫入前清理已有數據Insert Overwr」即可。這樣數據在導入的過程中會先清空數據後再導入,從而實現冪等。

數據導出的場景,如果數據是全量導出的,也可以用類似數據導入的方法,配置「導入前準備語句」,把原來的數據全部刪除後重新導入。另外如果數據源支持主鍵衝突設置時,可以通過「主鍵衝突」設置成「Replace Into」來實現數據的替換。

從上面的截圖裡可以看到,目前Dataworks本身就支持設置「出錯重試」,如果同步作業滿足冪等性要求的,可以大膽開啟這個設置,從而降低運維成本提高穩定性。

更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎


推薦閱讀:

建設數據倉庫的八個步驟
數據倉庫之數據模型
《數據架構》閱讀筆記(十)作業分析2
《Pentaho Kettle解決方案》閱讀筆記

TAG:ETL | 數據倉庫 | 同步 |