1. 程式人生 > 其它 >【轉】Stateful Functions 2.0 基於Apache Flink的事件驅動資料庫

【轉】Stateful Functions 2.0 基於Apache Flink的事件驅動資料庫

Stateful Functions 2.0 基於Apache Flink的事件驅動資料庫

轉自:https://blog.csdn.net/yanyan45/article/details/105622238

原文:https://flink.apache.org/news/2020/04/07/release-statefun-2.0.0.html#event-driven-database-vs-requestresponse-database

應用流式處理的事件驅動應用替換CRUD資料庫應用

2020-4-7, Apache Flink 團隊,宣佈了Stateful Functions (StateFun) 2.0正式釋出--Stateful Functions第一次作為Apache Flink專案一部分的釋出。這是個巨大的里程碑: Stateful Functions 2.0不僅僅是一個API升級,而是基於第一版基於Apache Flink之上構建的事件驅動資料庫(event-driven database)。

Stateful Functions 2.0 使有狀態性和彈性有效的結合在一起,實現了類似AWS Lambada和Kubernetes資源編排工具的快速縮放/縮放到零以及滾動升級的特性。

通過這些特性, Stateful Functions 2.0有效的解決了FaaS被詬病的兩個缺點:狀態一致性和函式間訊息交換效率。

事件驅動資料庫

Stateful Functions年初剛加入Apache Flink時,這個專案作為基於Flink的類庫,用於構建通用的事件驅動應用。用可以實現接受和傳送訊息的函式,並且管理持久化的變數狀態。Flink提供了一個高效的exactly-once狀態和訊息的基礎執行時。Stateful Functions 1.0受到FaaS的啟發,結合了流式處理和Actor程式設計。

在2.0版本中,Stateful Functions已經從Flink與JVM中解耦出來,只需通過服務呼叫他們。這可以使在Faas平臺,K8S部署或其他(微)服務上執行函式變為可行。

Flink根據接收的事件通過HTTP或gRPC呼叫函式,並提供狀態訪問。系統保證每個實體在任何狀態下僅會被消費一次,這樣通過隔離保證了狀態一致性。通過提供狀態訪問作為函式的一部分,函式本身可以被當做無狀態的,函式的管理變得更為簡單,並且帶來了快速縮放,縮放到零,無縫滾動升級等優點。

函式可以用任何能處理HTTP請求或者啟動gRPC服務的程式語言。StateFun project包含了一個輕量級的Python SDK,它能處理請求並分發到宣告的函式。我們的目標是微誒其他語言提供想死的SDK,如Go,JavaScript或者Rust。使用者無需寫任何Flink程式碼(或是JVM程式碼)。資料的輸入、輸出和函式入口可以通過YAML規範定義。

Flink程序(Flink JVM)不必執行任何使用者程式碼,當然為了優化應用程式效能也可以通過Embedded Functions使用程序。Flink中只需要儲存函式的狀態並提供函式間訊息傳遞的訊息面,小心地分發這些訊息/呼叫事件驅動函式,並保證一致性。而無需執行使用者應用特定的資料流。

實際上,Flink取代了資料庫的角色,但是它更適用於事件驅動的函式和服務。它通過整合狀態儲存,保證了函式或服務間傳遞訊息的有狀態性。因此,Stateful Functions 2.0也可以被當做基於Apache Flink的事件驅動資料庫。

事件驅動資料庫與請求/響應資料庫的對比

在傳統的資料庫或者Key/Value儲存(這裡稱之為請求/響應資料庫)中,應用需主動傳送一個查詢到資料庫(如SQL via JDBC,GET/PUT via HTTP)。然而,在StateFun這類事件驅動資料庫中,這個關係被反轉了:資料庫根據到達的訊息來呼叫函式或服務。這個特性非常適合FaaS或者事件驅動架構的應用。

基於請求/響應資料庫的應用中,資料庫只負責儲存狀態。函式或服務間的通訊通常一個獨立的服務層進行處理。相反,事件驅動資料庫以緊密整合的方式既儲存了狀態的儲存,又承擔了訊息的傳輸。

與Actor程式設計模型類似,狀態函式使用了可定址實體(addressable entities)的概念,這裡的實體被定義為一類具有唯一ID的函式。這些可定址實體擁有這些狀態,它是也訊息傳遞的目標。與Actor系統不同的是這些應用邏輯在系統外部,可定址實體也不在實體記憶體中儲存,而是Flink中管理的狀態。

狀態和一致性

事件驅動資料庫除了滿足了無狀態應用和FaaS的需求,同時也簡化了一致性狀態的管理。

想想以下這個例子,一個具有兩個入口的的應用,如兩個微服務(Service1, Service2)。Service1被呼叫更新了資料庫中的狀態,同時傳送請求到Service2。 假設這個呼叫請求失敗。 那麼通常情況下,Service1很難知道Service2是否正確的處理並更新了它的狀態。為了解決這個問題,我們引入了很多種技術,如保證服務的冪等性或者重試機制,使用commit/rollback協議,或者其他外部事務排程系統。在應用層解決這些問題就已經足夠複雜了,如果再引入資料庫到這些場景中,應用將變得難以維護。

同樣的場景中,事件驅動資料庫承擔了狀態管理和訊息傳遞的責任,以上問題變得很容易解決。假設資料庫的一個分片接收到了初始的訊息,並更新了它的狀態,呼叫了Service1,並將處理過的訊息路由到了另外一個分片,它將被分發到Service2。如果這個訊息在傳輸過程中發生錯誤,它可能傳輸失敗或成功,然後我們並不能確定。因為資料庫負責狀態管理和訊息傳遞,它可以提供通用的解決方案來保證兩個資料的一致性,例如通過事務或者consistent snapshots。應用的函式是無狀態的,他們的呼叫沒有任何副作用,這也就意味著我們可以重複呼叫它們,而不用擔心一致性問題。

這也是過去幾年中,我們從流式處理技術開發過程中總結的寶貴經驗:狀態的訪問與更新必須與訊息傳遞進行整合。它在狀態訪問和計算瓶頸等場景中帶給你一致性,可擴充套件性和反壓性。

儘管狀態管理和計算任務被物理的切割開,排程和分發的函式呼叫依然被整合在狀態管理中,也就是說為了保證一致性,它們的物理位置相同。

Remote, Co-located or Embedded Functions

函式可以根據應用的耦合性,獨立擴充套件性和效能開銷以不同的方式部署。每個函式模組都可以不同,一些函式可以遠端執行,而另外一些可以使用嵌入式執行。

遠端函式(Remote Functions)

遠端函式是上文中主要討論的方式,函式被部署在Flink叢集之外。狀態管理和訊息傳遞層(如Flink程序)和函式層都被可以被單獨部署與縮放。所有函式通過遠端服務終結點進行遠端呼叫。

與資料庫提供標準化協議(如ODBC/JDBC等傳統關係資料,基於REST的Key/value儲存)訪問類似,StateFun 2.0通過一個基於HTTP或gRPC的標準協議呼叫函式和服務。

本地函式(Co-located Functions)

另外一種部署方式被稱為Co-located Functions,函式被執行在與Flink JVM相同的位置。在這種模式下,每個Flink TaskMananger只與“臨近”的函式通訊。一個通用的方式就是使用K8S類似的系統將Flink容器和函式容器定義在同一個POD下,它們通過pod的本地網路進行通訊。

這個模式支援不同的程式語言,同時避免了通過服務/閘道器/負載均衡進行呼叫,但是無法將狀態和計算單元獨立的縮放。

這個部署模式類似於 Apache Beam’s的適配層和Flink的Python API,他們被部署在無需JVM執行時的環境中。

嵌入式函式(Embedded Functions)

嵌入式函式是Stateful Functions 1.0支援的模式,支援Flink的 Java/Scala流式處理API。函式被部署在JVM中,並訊息可以直接呼叫和訪問狀態。這是最高效的方式,然而僅允許JVM支援語言。

以資料庫作為類比, 嵌入式函式有點像儲存過程, 然而更嚴格的講:這裡的函式是實現了標準介面的Java/Scala/Kotlin函式。

載入資料到資料庫

當構建一個有狀態應用時,通常不會從一個完全空的資料庫開始。通常,應用有它的初始狀態,例如一個“bootstrap”狀態,或者恢復前一個版本的狀態。當使用資料庫時,我們可以簡單的批量載入這些資料。

同樣的步驟可以通過包含初始狀態的Flink的savepoint實現。Savepoints是分佈流式處理應用的狀態快照,將它傳進Flink後,Flink可以這個狀態進行恢復。可以把它們當做資料庫轉儲檔案,但是是一個分散式分散式流處理資料庫。在StateFun例子中,savepoint包含了函式的狀態。