實時決策系統中 OpenMLDB 的常見架構整合方式

4PD開發者社群發表於2023-04-05

OpenMLDB 提供了一個線上線下一致性的實時特徵計算平臺。對於如何在實際業務系統中整合 OpenMLDB,構建完整的機器學習平臺,OpenMLDB 提供了靈活的支援。本文關注基於 OpenMLDB,在企業級業務系統中使用的常見架構。我們主要關注儲存和計算兩個方面:

  • 離線上資料儲存架構:如何合理的進行離線和線上資料的儲存,並維持離線上資料的一致性。
  • 實時決策應用架構:如何基於 OpenMLDB 的實時請求計算模式構建線上應用,包含常見的事中決策和實時查詢應用架構。

離線上資料的儲存架構

由於不同的效能和資料量的需求,在一般情況下,OpenMLDB 的離線和線上資料在物理上是分開儲存:

  • 線上資料儲存:OpenMLDB 提供了一個高效的實時資料庫(基於記憶體或者磁碟),主要目的為儲存線上資料用於實時特徵計算,而非全量資料。其主要特點為:

    • 針對時序資料的毫秒級訪問,預設基於記憶體
    • 具備資料過期自動淘汰的能力(TTL),TTL 可以根據表格粒度進行設定,用於線資料庫僅存放必需的時間視窗內的資料
    • 預設基於記憶體的儲存引擎雖然效能較高,但是可能存在記憶體消耗量較大的問題,可以在滿足效能要求的前提下使用基於磁碟的儲存引擎
  • 離線數倉:OpenMLDB 本身並不提供獨立的離線儲存引擎,可以靈活支援不同的離線數倉和架構形式。

以下討論常見的離線和線上資料的儲存架構。

全量資料儲存於實時資料庫(不推薦)

file

使用者可以選擇把全量資料儲存於 OpenMLDB 的實時資料庫,此種使用方式帶來的優勢是使用簡單,並且物理上僅有一份資料,也節省了管理維護成本。但此種方式在實際使用中較少使用,主要有以下潛在問題:

  • 全量資料一般較大,而 OpenMLDB 為了保證線上效能,預設使用了基於記憶體的儲存引擎,基於記憶體儲存全量資料會帶來較大的硬體成本負擔。
  • OpenMLDB 雖然也提供了基於磁碟的儲存引擎,但是磁碟儲存會帶來 3-7x 左右的效能下降,可能無法滿足某些線上業務場景需求。
  • 離線和線上資料儲存於同一個物理介質,可能會對線上實時計算的效能和穩定性帶來較大的負面影響。

因此在實際中,為了充分發揮 OpenMLDB 的實時計算能力,我們並不推薦儲存全量資料在 OpenMLDB,而是和離線數倉配合使用。

離線上資料儲存分離管理架構

file

目前在實際使用場景中,大部分使用者基於此種離線上儲存分離管理的架構。基於此種架構,資料會同時寫入到離線數倉和實時資料庫。OpenMLDB 的實時資料庫會設定表格級別的資料過期(TTL)。此種設定會對應於所需要的特徵指令碼內的時間視窗的大小,即實時資料庫只儲存用於實時特徵計算的必要的資料,而非全量資料。相關注意點:

  • 實際企業架構中,資料來源一般基於 Kafka 等訊息佇列的訂閱機制。不同的應用會去分別消費資料。在此種架構下,寫入到 OpenMLDB 的實時資料庫的通路,以及儲存到離線數倉的通路,可以認為是兩個獨立的消費者。
  • 如果並非基於訊息佇列的訂閱機制,也可以認為在 OpenMLDB 上游有一個或者多個資料接收程式,用於實現和管理 OpenMLDB 的線上儲存以及離線儲存。
  • OpenMLDB 實時資料庫的過期時間需要正確的被設定,使得實時資料庫記憶體儲的資料可以被用於正確的實時特徵計算。
  • 此種架構的主要缺點是管理稍複雜,從使用者視角看到了離線和線上兩份資料需要本單獨管理。

離線上資料儲存統一檢視架構(預期 v0.7.4 支援)

file

在此種離線上資料統一檢視的架構下,簡化了使用者視角對於離線上資料的同步和管理。我們預期會在 0.7.4 版本推出一個自動化的從實時資料庫到離線數倉的同步機制。在此種架構下,雖然在物理上我們依然有實時資料庫和離線數倉兩個儲存引擎,但是在使用者視角上,可以僅關注一個寫入通路。使用者只需要將新的資料寫入 OpenMLDB 實時資料庫,設定好實時到離線的同步機制,OpenMLDB 即可以自動化地將資料實時或者定時地同步到一個或者多個離線數倉。OpenMLDB 的實時資料庫依然依靠資料過期機制僅儲存用於線上特徵計算的資料,而離線數倉會保留所有全量資料。該功能預期在 2023 年 4 月上旬的 0.7.4 版本會加入。

實時決策應用架構

實時請求計算模式

在瞭解實時決策應用架構前,需要先了解 OpenMLDB 線上實時計算引擎提供的基於請求的實時計算模式,其主要包含三個步驟:

  1. 客戶端透過 REST APIs 或者 OpenMLDB SDKs 傳送計算請求(request),該請求可選帶有當前事件的狀態資訊資料,比如當前刷卡事件的刷卡金額、商鋪 ID 等。
  2. OpenMLDB 實時引擎接受該請求,根據已經部署上線的特徵計算邏輯,進行按需(on-demand)的實時特徵計算
  3. OpenMLDB 將實時計算結果返回給發起請求的客戶端,完成本次實時計算請求

本文將從實際應用場景出發,闡述基於 OpenMLDB 的實時請求計算模式的常見應用搭建架構。我們會介紹兩種常見的應用架構。

事中決策應用架構

OpenMLDB 的預設計算模式為支援事中決策的應用,其字面意義即為在事件發生過程中的決策行為。因此其主要特點為,當前事件產生的行為資料也會被納入決策考量中。其最典型的例子即為信用卡反欺詐:當一筆信用卡交易發生時,反欺詐系統會在交易真正落實之前進行決策,同時把當前的刷卡行為資料(比如當前刷卡的金額、時間、地點等),連同近期一段時間視窗內的資料進行一起考量決策。該架構在反欺詐、風控等領域被廣泛採用。

我們來看一個具體的例子。下圖顯示了當一個刷卡交易發生時,整個系統發生的功能邏輯。可以看到,系統中維護了歷史交易記錄,當一個新的交易行為發生時,當前的行為資料會被虛擬插入表格中,連同近期的交易記錄一起,做特徵計算,再給到模型推理,最後判斷是否為欺詐交易。

file

注意,上圖中顯示了新來的刷卡記錄資料被虛擬插入到歷史交易表,這是因為在 OpenMLDB 的請求模式中,系統預設就會把請求所帶的事中資料虛擬地插入到表格中,參與到整體特徵計算中(如果特殊情況下不需要當前請求行資訊參與決策,可以使用 EXCLUDE CURRENT_ROW 關鍵字,詳見 “附錄:EXCLUDE CURRENT_ROW 語義解釋”)。同時,在普遍情況下,當前請求行對於後續的決策也是有用的,因此其在完成當前的特徵計算以後,應該被真正的物理插入到資料庫。為了構建一個如上業務流程的事中決策系統,我們下面列舉一個典型的架構流程圖。

實時決策5.jpg

該架構基於 OpenMLDB SDK,做到了嚴格的事中決策,該流程包含兩個階段:

  1. 上圖中的步驟1、2、3,實際構成了一次 OpenMLDB 的實時請求,並且本次請求附帶了本次事件發生時候的必需的資料(卡號、刷卡金額、時間戳)。
  2. 完成實時請求以後,客戶端透過 OpenMLDB SDK 額外發起了一次資料插入請求,把當前的交易行為資料插入到 OpenMLDB,以供後續的實時請求計算使用。

以上基於 OpenMLDB SDK 的嚴格事中決策架構,是 OpenMLDB 預設並且所推薦的架構。在實際的企業應用架構中,由於外圍耦合架構或者內部許可權的複雜性,也會存在一些變種。比如,資料寫入的通路被完全分離開來,使用 Kafka 或者其他方式進行單獨的資料寫入。但是,該架構如果沒有做額外的強制性保障,可能會存在讀寫順序上的問題,從而導致視窗內資料重複或者缺少計算。因此,一般情況下,我們還是推薦使用上圖的嚴格的事中決策架構。

實時查詢應用架構

在一些推薦類應用場景中,往往需要在某一個時間點做一次實時計算的查詢,該查詢本身不帶有具備意義的資料。比如當使用者進行商品瀏覽時,需要在使用者開啟瀏覽器時,實時查詢過去十分鐘內平臺上符合該使用者興趣的最熱門的商品資料,進行商品排序推薦。在此類場景下,使用者的請求和相關物料資料的寫入可以完全解耦開,同時使用者的請求並不帶有具備意義的資料,僅僅是為了觸發一次實時計算請求,可以使用 SQL 關鍵字 EXCLUDE CURRENT_ROW 達到該目的。

file

可以看到,在上面的架構中,實時請求(只讀)和資料的寫入通路被解耦開。

  • 對於資料寫入通路,使用者可以透過流式(比如 Kafka connector)或者 OpenMLDB SDK 的方式,將相關物料資料不斷的寫入到 OpenMLDB 的資料庫內
  • 對於實時請求部分,主要有兩個特點:

    • 請求完成以後不再需要額外的步驟寫入實時資料(相關資料由資料寫入通路完成,請求本身不帶有具備意義的資料)
    • 由於 OpenMLDB 預設的請求計算行為會進行虛擬的資料插入,但是在這種架構下,實時請求所帶的資料不再具備意義。因此,我們需要使用擴充套件的 SQL 關鍵字 EXCLUDE CURRENT_ROW,來達到該目的。

其他擴充套件架構

除了上面介紹的兩種架構,OpenMLDB 也可以擴充套件為支援離線特徵線上查詢架構,以及支援流式特徵等架構。我們將在後續的文章中逐步介紹其他實際中應用到的企業級架構。

附錄:EXCLUDE CURRENT_ROW 語義解釋

OpenMLDB 的請求模式預設會把當前資料行虛擬插入到表格,一起參與視窗計算。如果不需要當前行的資料參與計算,可以使用 EXCLUDE CURRENT_ROW 。該語法把當前請求行的資料排除在視窗計算以外,但是請求行提供的 PARTITION BY KEYORDER BY KEY 依然需要被使用,用於定位請求的具體資料和時間視窗。

以下使用一個具體例子來說明其語義。假設其用於儲存交易記錄的資料表格 txn 的 schema 如下。

Columncard_idamouttxn_time
Typestringdoubletimestamp

我們使用如下加上了 EXCLUDE CURRENT_ROW 的SQL:

SELECT card_id, sum(amount) OVER (w1) AS w1_amount_sum FROM txn 
    WINDOW w1 AS (PARTITION BY card_id ORDER BY txn_time 
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE CURRENT_ROW);

該語句定義了一個以 card_id 為 key,根據 txn_time 進行排序,並且基於當前請求行往前包括兩行的一個視窗;同時,因為定義了 EXCLUDE CURRENT_ROW,當前請求行實際不進入視窗進行計算。

簡化期間,我們假設該表格僅存在以下兩條資料:

 --------- ----------- --------------- 
  card_id   amount      txn_time       
 --------- ----------- --------------- 
  aaa       22.000000   1636097890000  
  aaa       20.000000   1636097290000  
 --------- ----------- --------------- 

我們傳送實時計算請求,其中包含的請求資料為:

Columncard_idamounttxn_time
Valueaaa23.01637000000000
說明用於定位視窗的 key該列資訊實際不進入視窗計算用於定位視窗的時間戳

如果不使用 EXCLUDE CURRENT_ROW,則當前請求行,以及資料庫裡已經包含的兩行均會進入視窗中,參與實時計算,其返回結果為 "aaa, 65.0"。但是,由於其部署的 SQL 中帶有 EXCLUDE CURRENT_ROW,則當前行不進入視窗計算,所以其返回值實際為 "aaa, 42.0"。注意,雖然當前行的值 amount 並不進入視窗進行計算,但是其 card_id (用於標記分類的 key),以及 txn_time (用於標記時間戳資訊),依然需要被正確設定,用於尋找正確的視窗資料。

相關文章