SODBASE CEP學習(六):流式計算中的存儲和ETL

許多流式計算應用離不開存儲,也就是把數據存在硬盤上,例如歷史數據的保存。畢竟硬盤適合長期地存儲大量數據。在介紹具體方法之前,先講一個實際項目裏經常要用到的原則,那就是:存儲讀寫速度要和內存計算速度匹配。

怎麼理解呢?例如內存計算速度是10萬events/s,存儲讀寫速度是1萬events/s,那麼很容易引起數據不能及時寫到存儲中,而導致OOM等各種問題。還有,硬盤讀寫的速度、網絡傳輸的速度經常受到外部因素的干擾,通常沒有內存計算速度穩定,這點也要考慮到。

所以流式計算中使用存儲,通常

(1)要設計緩存隊列,CEP引擎中一般有自帶的緩存隊列,實現IO和計算的異步。當然,SODBASE CEP中進一步增強了避免OOM和預警的機制。

(2)儘可能的將內存計算和存儲操作分離。原因:

一來是爲了更好地使用CEP引擎自帶的緩存隊列。

二來是爲了更好的管理。這樣,在存儲操作中可以更方便地使用批量寫入、通過計算減少寫入數據量,過濾掉不需要寫入的數據,從而提高存儲讀寫效率。

使用存儲的方法一般有兩類

第一類:在EPL中直接用。例如,在EPL中用Java函數,而Java函數又負責存儲讀寫。

第二類:使用輸入輸出適配器。

本文主要介紹使用輸入輸出適配器。最後介紹一下,爲什麼輸入適配器、CEP引擎、輸出適配器恰好也能作很好地應用在Extract Transformation Load (ETL) 操作中。

1. 關係型數據庫輸入輸出適配器

Mysql、Oracle、Sql server、postgresdb等都是關係型數據庫。不要小瞧關係數據庫,大部分數據存儲的企業應用可以用關係數據庫解決。Mysql集羣可以支撐億級用戶的特大型的互聯網應用。以mysql爲例,常用的3個輸出適配器:

(1)數據庫查詢

com.sodbase.outputadaptor.database.MysqlQueryAdaptor

作用:對於每個結果事件,查詢mysql數據庫,並將查詢的結果插入到新的流中

  0: stream name 查詢的結果插入到新的流的名稱
  1: database name
  2: user name
  3: password
  4: host name
  5: port
  6: sql  查詢sql,允許使用?{...}變量,通過輸出的事件屬性值,如:?{name}
  7: columnnames  e.g.   "name:string,age:double,ishappy:boolean" Three types "string,double,boolean" are supported

(2)數據庫更新

com.sodbase.outputadaptor.mysql.MysqlSqlExecutionAdaptor

作用:對於每個結果事件,執行sql語句,如DML、數據更新等
參數:

   0     databasename 
   1     dbusername 
   2     dbpassword 
   3     hostname 
   4     dbport 
   5    sql 

        inputStreamConnected = params[6];//sql執行結束後,發事件給流inputStreamConnected,這個事件只有時間戳屬性

(3)數據庫備份

com.sodbase.outputadaptor.mysql.MysqlBackupOutputAdaptor

作用:鎖表執行sql語句,類似於上面的adatpor,通常用於執行備份語句。

   0     databasename 
   1     dbusername
   2     dbpassword 
   3     hostname 
   4     dbport
   5     sql
   6     tablename //用於鎖定所需備份的表
   7     inputStreamConnected //sql執行結束後,發事件給流inputStreamConnected,這個事件只有時間戳屬性


其它Oracle、Sql server、postgresdb適配器類似,也都支持。

另外,還有一個輸入適配器com.sodbase.inputadaptor.database.MySqlInputAdaptor,EPL啓動時查詢數據庫的數據插入到流中。

應用場景,例如:定時、超時任務防止系統宕機後丟失,將沒有執行過的任務存在數據庫中,重啓服務器時,就會把這些任務再加到事件流,也就是任務隊列裏。


2. Nosql適配器和分佈式緩存適配器

支持cassandra、hbase、monogodb, 巨杉等nosql數據庫,支持redis等分佈式緩存數據庫,用戶也可以方便地自定義適配器。

3. 數據庫分批寫入

如果大家還記得kleen closure操作符,用它可以方便地做數據庫分批寫入,解決存儲讀寫瓶頸問題

CREATE QUERY tensecondsdata
SELECT tostring(T2.price) AS pricebatch, tostring(T2.name) AS namebatch 
FROM T1:timer,T2:stock,T3:timer 
PATTERN T1;T2^+;T3  
WHERE T1._start_time_=T3._start_time_-10000  
WITHIN 10000


這個EPL將數據分成10s爲一批。timer是定時輸入適配器,週期10s。如果要精確,可以用兩個定時輸入timer1和timer2,週期都是10s,但起點相差1個單位時間(一般單位是ms)。這是因爲模式中T1._end_time_<T2._end_time_<T3._end_time_是一個開集合,我們用兩個timer1,可以做成一個半開半閉集合,不漏掉恰好在timer時間點上的數據。

CREATE QUERY tensecondsdata
SELECT tostring(T2.price) AS pricebatch, tostring(T2.name) AS namebatch 
FROM T1:timer1,T2:stock,T3:timer2
PATTERN T1;T2^+;T3  
WHERE T1._start_time_=T3._start_time_-10001 
WITHIN 10001


4. 應用示例

4.1 電壓監測

本節將介紹實時測量監測系統中電壓監測數據的監測、存儲示例。類似原理可以適用到發電數據、設備狀態、水情、空氣、水情、水質、污染源等監測應用中。數據存儲也可以推廣到各類關係數據庫、Nosql數據庫。

4.1.1保存實時測量數據

注意這裏是爲了讓大家更好了解細節,所以用給出EPL和XML。建議大家用SODBASE Studio建模。

CREATE QUERY VD0002 
SELECT T1.lineid AS lineid,T1.voltagevalue AS voltagevalue 
FROM T1:VD0000_output 
PATTERN T1 
WITHIN 0
VD0000_output是電壓測量數據流
    <outputAdaptors>
        <isOutputAsSelection>true</isOutputAsSelection>
        <outputAdaptorClassName>com.sodbase.outputadaptor.mysql.MysqlSqlExecutionAdaptor</outputAdaptorClassName>
        <adaptorParams>voltage</adaptorParams>
        <adaptorParams>user</adaptorParams>
        <adaptorParams>password</adaptorParams>
        <adaptorParams>192.168.1.3</adaptorParams>
        <adaptorParams>3306</adaptorParams>
        <adaptorParams>insert into historicalvoltage(lineid,voltagevalue,timestamp) values('?{lineid}',?{voltagevalue},'?{_end_time_}')</adaptorParams>
        <adaptorParams>operationcompletestream</adaptorParams>
        <isExternal>false</isExternal>
        <queryName>VD0002</queryName>
    </outputAdaptors>
?{}是在sql語句中使用事件字段的值

4.1.2定時備份

有時用戶需要將歷史數據進行備份

CREATE QUERY VD0003 
SELECT JAVA:com.example.voltage.Voltage:getDate() AS date, JAVA:com.example.voltage.Voltage:getDayStarttime() AS starttime, JAVA:com.example.voltage.Voltage:getDayEndtime() AS endtime 
FROM T1:timer 
PATTERN T1 
WITHIN 0
timer數據流是有定時觸發輸入適配器生成的,用法見前面介紹EPL的文章
    <outputAdaptors>
        <isOutputAsSelection>true</isOutputAsSelection>
        <outputAdaptorClassName>com.sodbase.outputadaptor.mysql.MysqlBackupOutputAdaptor</outputAdaptorClassName>
        <adaptorParams>voltage</adaptorParams>
        <adaptorParams>username</adaptorParams>
        <adaptorParams>password</adaptorParams>
        <adaptorParams>192.168.1.3</adaptorParams>
        <adaptorParams>3306</adaptorParams>
        <adaptorParams>select * into outfile 'D:/?{date}.txt' from historicalvoltage where timestamp>=?{starttime} and timestamp<?{endtime}</adaptorParams>
        <adaptorParams>historicalvoltage</adaptorParams>
        <adaptorParams>endbackupmessage</adaptorParams>
        <isExternal>false</isExternal>
        <queryName>VD0003</queryName>
    </outputAdaptors>

4.1.3 做每日統計

假設每天定時備份完,需要做日統計

CREATE QUERY VD0003_2 
SELECT JAVA:com.example.voltage.Voltage:getYesterdayDate() AS date 
FROM T1:endbackupmessage 
PATTERN T1 
WITHIN 0

輸出適配器

    <outputAdaptors>
        <isOutputAsSelection>true</isOutputAsSelection>
        <outputAdaptorClassName>com.sodbase.outputadaptor.mysql.MysqlSqlExecutionAdaptor</outputAdaptorClassName>
        <adaptorParams>voltage</adaptorParams>
        <adaptorParams>user</adaptorParams>
        <adaptorParams>password</adaptorParams>
        <adaptorParams>192.168.1.3</adaptorParams>
        <adaptorParams>3306</adaptorParams>
        <adaptorParams>insert into daystatistic(lineid,date,upbound,bottombound) select lineid as lineid,?{date} as date, max(voltagevalue) as upbound,min(voltagevalue) as bottombound from historicalvoltage group by lineid</adaptorParams>
        <adaptorParams>endstatisticmessage</adaptorParams>
        <isExternal>false</isExternal>
        <queryName>VD0003_2</queryName>
    </outputAdaptors>

4.2 船舶活動區域監測

本節介紹GIS實時監測領域的應用示例,即監測船舶是否偏離了規定航線或規定活動區域。原理也可以應用到其他GIS實時監測應用中。示例場景爲作業的船隻通常有一定的活動範圍,如果船隻出現在異常的海域,應該向海岸管理人員預警提示。

具體EPL就不給出了,參考附件中的“時間處理拓撲圖”。

filter1負責當船舶實時位置上報時,查詢正常區域模型數據庫。

filter2負責根據船舶實時位置更新正常區域模型,即此船隻正常活動的區域(四個座標點形成的矩形區域)。

ARA負責判斷船舶是否偏離了正常航行區域,並進行預警。

整個拓撲圖中的事件驅動架構則是由級聯輸入輸出適配器完成的。級聯輸入適配器com.sodbase.inputadaptor.StubInputAdaptor級聯輸出適配器com.sodbase.outputadaptor.connection.ConnectToSodInputOutputAdaptor前文有介紹。

4.3 ETL、數據庫監測、文件監測

ETL說通俗一些,其實都是是定時監測數據庫(關係型或nosql數據庫),然後根據EPL規則將數據進行轉化。結果輸出到另一個數據庫中,一般是數據倉庫中,那就是ETL。

如果結果輸出到實時圖表顯示,那就是一種數據監測。有很多場合,數據庫作爲了中間媒介來觀察數據的變化,也是一種數據監控的方法。

4.3.1 ETL示例

例:在一些項目中,需要把數據放到關係型數據庫更好地做OLAP分析,如將數據從Nosql數據庫同步到關係型數據庫集羣


例:數據質量管理、ETL、經營分析系統中將兩個數據庫表中的數據導入到DataWarehouse,統一gender字段的編碼。

CREATE QUERY DQ0002 
SELECT * 
FROM T1:mysql數據輸入,T2:mysql數據輸入2 
PATTERN T1|T2 
WITHIN 0 
DQ0002的輸出適配器用 級聯節點(no watermark),輸出到流DQ0002_output
mysql數據輸入、mysql數據輸入2用的是mysql輸入適配器。
CREATE QUERY DQ0002_output 
SELECT T1.name AS name,JAVA:dq.Code:standardizeGender(T1.gender) AS gender,T1.age AS age 
FROM T1:DQ0002_output 
PATTERN T1 
WITHIN 0 
DQ0002_output可以接數據存儲寫入的適配器。


4.3.2 數據庫、文件監測

有些情況,也會定時監測是其他數據源,比如文件、文件夾、各類型URI,和監測數據庫數據的原理是一樣的,在經營分析系統、數據質量管理等項目中也經常會用到。


SODBASE CEP用於輕鬆、高效實施數據監測、監控類項目微笑。EPL語法見SODSQL寫法與示例。圖形化建模請使用SODBASE Studio

使用SODBASE產品的程序員現在可領禮品啦 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章