Flink基礎系列34-Flink CEP簡介 一.什麼是CEP 二.CEP特點 三. Pattern API 參考:

一.什麼是CEP

  1. 複雜事件處理(Complex Event Processing,CEP)

  2. Flink CEP是在Flink中實現的複雜事件處理(CEP)庫

  3. CEP允許在無休止的事件流中檢測事件模式,讓我們有機會掌握數據中重要的部分

  4. 一個或多個由簡單事件構成的事件流通過一定的規則匹配,然後輸出用戶想得到的數據——滿足規則的複雜事件

二.CEP特點

目標:從有序的簡單事件流中發現一些高階特徵

輸入:一個或多個由簡單事件構成的事件流

處理:識別簡單事件之間的內在聯繫,多個符合一定規則的簡單事件構成複雜事件

輸出:滿足規則的複雜事件

三. Pattern API

處理事件的規則,被叫做"模式"(Pattern)

Flink CEP提供了Pattern API,用於對輸入流數據進行復雜事件規則定義,用來提取符合規則的時間序列

DataStream<Event> input = ...
// 定義一個Pattern
Pattern<Event, Event> pattern = Pattern.<Event>begin("start").where(...)
  .next("middle").subtype(SubEvent.class).where(...)
  .followedBy("end").where(...);
// 將創建好的Pattern應用到輸入事件流上
PatternStream<Event> patternStream = CEP.pattern(input,pattern);
// 檢出匹配事件序列,處理得到結果
DataStream<Alert> result = patternStream.select(...);

3.1 個體模式(Individual Patterns)

組成複雜規則的每一個單獨的模式定義,就是"個體模式"

start.times(3).where(new SimpleCondition<Event>() {...})

個體模式可以包括"單例(singleton)模式"和"循環(looping)模式"

單例模式只接收一個事件,而循環模式可以接收多個

量詞(Quantifier)
可以在一個個體模式後追加量詞,也就是指定循環次數

//匹配出現4次
start.times(4)
//匹配出現2/3/4次
start.time(2,4).greedy
//匹配出現0或者4次
start.times(4).optional
//匹配出現1次或者多次
start.oneOrMore
//匹配出現2,3,4次
start.times(2,4)
//匹配出現0次,2次或者多次,並且儘可能多的重複匹配
start.timesOrMore(2),optional.greedy

條件(Condition)

  1. 每個模式都需要指定觸發條件,作爲模式是否接受事件進入的判斷依據
  2. CEP中的個體模式主要通過調用.where(),.or()和.until()來指定條件
  3. 按不同的調用方式,可以分成以下幾類
    1)簡單條件(Simple Condition)
    通過.where()方法對事件中的字段進行判斷篩選,決定是否接受該事件
start.where(new SimpleCondition<Event>){
  @Override
  public boolean filter(Event value) throws Exception{
    return value.getName.startsWith("foo");
  }
}

2)組合條件(Combining Condition)
將簡單條件進行合併;.or()方法表示或邏輯相連,where的直接組合就是AND

pattern.where(event => ... /* some condition */).or(event => ... /* or condition */)

3)終止條件(Stop Condition)
如果使用了oneOrMore或者oneOrMore.optional,建議使用.until()作爲終止條件,以便清理狀態

4)迭代條件(Iterative Condition)
能夠對模式之前所有接收的事件進行處理
可以調用ctx.getEventsForPattern("name")

.where(new IterativeCondition<Event>(){...})

3.2 組合模式(Combining Patterns)

組合模式(Combining Patterns)也叫模式序列。
1)很多個體模式組合起來,就形成了整個的模式序列
2)模式序列必須以一個"初始模式"開始

Pattern<Event, Event> start = Pattern.<Event>begin("start")
  1. 嚴格近鄰(Strict Contiguity)
    1)所有事件按照嚴格的順序出現,中間沒有任何不匹配的事件,由.next()指定
    2)例如對於模式"a next b",事件序列[a,c,b1,b2]沒有匹配

  2. 寬鬆近鄰(Relaxed Contiguity)
    1)允許中間出現不匹配的事件,由.followedBy()指定
    2)例如對於模式"a followedBy b",事件序列[a,c,b1,b2]匹配爲[a,b1]

  3. 非確定性寬鬆近鄰(Non-Deterministic Relaxed Contiguity)
    1)進一步放寬條件,之前已經匹配過的事件也可以再次使用,由.followByAny()指定
    2)例如對於模式"a followedAny b",事件序列[a,c,b1,b2]匹配爲{a,b1},{a,b2}

  4. 除了以上模式序列外,還可以定義"不希望出現某種近鄰關係":
    1).notNext() 不嚴格近鄰
    2).notFollowedBy()不在兩個事件之間發生
    (eg,a not FollowedBy c,a Followed By b,a希望之後出現b,且不希望ab之間出現c)

  5. 需要注意:
    1)所有模式序列必須以.begin()開始
    2)模式序列不能以.notFollowedBy()結束
    3)"not "類型的模式不能被optional 所修飾
    4)此外,還可以爲模式指定事件約束,用來要求在多長時間內匹配有效:
    next.within(Time.seconds(10))

3.3 模式組

3.3.1 模式的檢測

指定要查找的模式序列後,就可以將其應用於輸入流以檢測潛在匹配
調用CEP.pattern(),給定輸入流和模式,就能得到一個PatternStream

DataStream<Event> input = ...
Pattern<Event, Event> pattern = Pattern.<Event>begin("start").where(...)...

PatternStream<Event> patternStream = CEP.pattern(input, pattern);

3.3.2 匹配事件提取

  1. 創建PatternStrean之後,就可以應用select或者flatselect方法,從檢測到的事件序列中提取事件了
  2. select()方法需要輸入一個select function作爲參數,每個成功匹配的事件序列都會調用它
  3. select() 以一個Map<String,List<IN]>> 來接收匹配到的事件序列,其中Key就是每個模式的名稱,而value就是所有接收到的事件的List類型
public OUT select(Map<String, List<IN>> pattern) throws Exception {
  IN startEvent = pattern.get("start").get(0);
  IN endEvent = pattern.get("end").get(0);
  return new OUT(startEvent, endEvent);
}

3.3.3 超時事件提取

當一個模式通過within關鍵字定義了檢測窗口時間時,部分事件序列可能因爲超過窗口長度而被丟棄;爲了能夠處理這些超時的部分匹配,select和flatSelect API調用允許指定超時處理程序

超時處理程序會接收到目前爲止由模式匹配到的所有事件,由一個OutputTag定義接收到的超時事件序列

PatternStream<Event> patternStream = CEP.pattern(input, pattern);
OutputTag<String> outputTag = new OutputTag<String>("side-output"){};

SingleOutputStreamOperator<ComplexEvent> flatResult = 
  patternStream.flatSelect(
  outputTag,
  new PatternFlatTimeoutFunction<Event, TimeoutEvent>() {...},
  new PatternFlatSelectFunction<Event, ComplexEvent>() {...}
);
DataStream<TimeoutEvent> timeoutFlatResult = 
  flatResult.getSideOutput(outputTag);

參考:

  1. https://www.bilibili.com/video/BV1qy4y1q728
  2. https://ashiamd.github.io/docsify-notes/#/study/BigData/Flink/%E5%B0%9A%E7%A1%85%E8%B0%B7Flink%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0?id=_15-cep
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章