什麼是數據流
數據流的屬性
數據流是無邊界(無限且持續增長)數據集的抽象表示
例如:信用卡交易,包裹遞送,遊戲物體的移動
數據流(事件流)的其他屬性
- 事件流是有序的 先存錢再花錢
- 事件流是不可變的 訂單取消並不是說它就消失了
- 事件流是可重播的 讓現代業務領域的流式處理大獲成功
非結構化的鍵值對,半結構化的JSON,結構化的Avro
3種編程範式
- 請求與響應範式,延遲最小的一種範式,處理模式一般是程序向系統發出請求,然後等待響應。例如OLTP系統
- 批處理,具有高延遲和高吞吐量的特點。處理模式一般是通過定時任務定時定頻率的觸發任務執行。例如OLAP系統,數據倉庫,商業智能
- 流式處理,延遲介於請求與響應模式和批處理模式,適合那些業務流程持續進行,既不要求亞豪秒響應,也接受不了等到第二天才知道結果。例如交易報警,根據工序實時調整價格
流式處理的概念
時間
事件時間:事件發生的時間
處理時間:應用程序接受到時間之後對其處理的時間
狀態
事件與事件之間的聯繫,保存在應用程序本地變量中
- 本地狀態:只能被單個應用程序實例訪問,一般使用內嵌在應用程序中的數據庫維護和管理
- 外部狀態:能被多個應用程序訪問,一般使用Nosql數據庫存儲
流和表的二元性
- 表都有一個主鍵,幷包含一系列通過schema定義的屬性,是事件的結果。
- 流包含了一系列事件,是事件的過程。
將錶轉化爲流,需要應用流裏包含所有變更。
時間窗口
大部分針對流的操作都是基於時間窗口的:移動平均數,一週銷量最好的鞋子
- 窗口的大小。窗口越小,越快發現變更,但是噪聲也越大。窗口越大,變更越平滑,但是延遲很嚴重
- 窗口移動的頻率。5分鐘的平均數可以每分鐘變化一次
- 窗口可更新時間。已經計算了窗口大小的事件邏輯,但是後面又有對應時間段的事件發生。
流式處理的設計模式
每個流式處理系統都不一樣,從生產者和消費者,到使用Sprk Streaming和機器學習軟件包的複雜集羣。
- 單個事件處理(map模式,filter模式)
這種模式無需維護狀態,每個事件都是獨立處理
- 使用本地狀態
大部分流式處理應用程序關心的是如何聚合信息。特別是基於時間窗口的聚合
例如:基於某時間段的股票信息
使用本地狀態考慮的問題
a) 內存使用:應用實例必須有足夠內存
b) 持久化:確保程序關閉不會丟失狀態,重啓或切換另一個實例可恢復狀態
c) 再均衡:重分配分區時,失去分區的實例必須把最後的狀態保存起來 - 多階段處理和重分區
本地狀態:很好的實現了按組聚合操作
問題:怎麼實現跨應用實例聚合 例如:計算前10☞股票
解決:兩階段解決-a) 計算每支股票的漲跌,都寫到單個分區中
b) 另一個應用程序讀取這個分區,找出前10支股票
- 使用外部查找-流和表的連接
將外部數據和流集成到一起,比如:使用db的規則驗證事務,將用戶信息填充到點擊事件中
缺點:外部查詢帶來延遲,外部系統接受不了這麼高的負載
解決:緩存數據庫
捕捉數據庫的變更事件並形成事件流(CDC-change data capture)
某些連接器可以執行cdc任務,把錶轉換爲事件流,一旦數據庫發生變更,則更新本地緩存
5. 流與流的連接
通過流來表示表,就可以忽略大部分歷史事件,因爲只關心表的當前狀態。
連接流定義:將兩個流中具有相同鍵且發生在相同窗口內的事件匹配起來
例如:用戶輸入瀏覽器的搜索事件流+用戶對搜索結果的點擊事件流,來分析 哪一個搜索的熱度更高???
6. 亂序的事件
a)識別亂序事件
b)規定可重排亂序的時間範圍
c)具有亂序重排的能力
d)具備更新結果的能力
Stremas示例
底層的Processor API,高級的Streams API
流式處理就是 爲事件流定義轉換鏈
拓撲topology:一個有向圖,包含幾個轉換事件流的過程。
- map-filter簡單聚合
無需安裝任何軟件,就可運行實例。只需啓動多個實例就可擁有一個集羣
public class WordCount{
public static void main(String[] args){
Properties props=new Properties();
props.put(StreamsConfig.Application_id,"wordcount"); //每個應用程序都要有一個應用ID
props.put(StreamsConfig.ServersConfig,"ip:port"); // Kafka配置
KStreamBuilder builder=new KStreamBuilder(); //創建拓撲
KStream<String,String> source=builder.stream("wordcount-input"); //構件流並指向輸入主題
Pattern pattern=Pattern.compile("\\w+");
//1. 從主題讀取每一個事件就是一樣文字,然後將一行文字拆分成多個單詞,將單詞作爲事件的鍵,然後執行group by
source.flatMapValues(value.toLowerCase()).map(()->{
new KeyValue<Object,Object>(value,value)
})
//2. 過濾單詞the
.filter((key,value)->{
!value.equals("the")
})
//3. 得到不重複的單詞集合__重新分區
.groupByKy()
//4. 計算每個集合的事件數
.count(“countStore”).mapValues(value->{
Long.toString(value).toStream(); //將結果轉爲String類型,方便kafak讀取結果
});
counts.to("wordcount-output");
}
}
KafkaStream kafkastream=new KafkaStreams(builder,props);
kafkastream.start();
Thread.sleep(5000);
Kafkastream.close();
-
基於時間窗口的聚合-股票的統計信息
從股票交易事件流中 讀取事件,然後計算沒5秒鐘內最好估盤價,交易股數,平均估盤價
估盤價:賣方願意出售的價格
要價規模:賣方願意在估盤價的基礎上 出售的股數
買入價:買方願意支付的價格 -
填充點擊事件流-演示流的連接