KafkaStrom 初探

https://www.cnblogs.com/warehouse/p/9521382.html   參考

        Kafka是0.10新引入的一個Feature。它是提供了對存儲於Kakfa內的數據進行流式處理和分析的功能。使得Kafka不再僅是一個消息引擎,而是往一個分佈式流處理平臺方向發展。

如下特點

簡單輕量級的Library,非常方便的嵌入到Java應用中,可以任意方式打包和部署。

除了Kafka外,無任何依賴。

充分利用Kafka的分區機制實現水平擴展和順序性保證。

通過可容錯的stage strore實現高效的狀態操作(比如windowed join 和agreegation)

支持正好一次處理語義

提供記錄級的處理能力,從而實現毫秒級的低延時。

支持基於事件事件的時間窗口,並且可以處理晚到的數據。

同時提供底層的處理原語Processror(類似於Strom的spout和bolt),以及高層抽象的DSL(類似Spark的map/group/reduce)

 

流式計算:

       在流式計算模型中,輸入是持續的,可以認爲時間是無界的,也就意味着永遠拿不到最全的數據進行計算.同時,計算結果也是持續輸出的,也即計算結果上是無界的。流式計算一般對實時結果要求較高,一般也是先定義目標計算,然後數據到來之後將計算邏輯用於數據。

爲什麼要使有Kakfa

當前已經有非常多的流式處理系統。最知名且應用最多的開源流式處理系統有Spark Stream和Apache Strom。Apache Strom應用廣泛,提供記錄級別的處理能力。當前也支持SQL  on Stream. 而Spark Stream基於Apache Spark,可以非常方便與圖計算,SQL處理等集成,功能強大,對於其他熟悉Spark應用開發的人員而言使用門檻低。

   既然Apache Spark與Apache Strom擁有如此多的優勢,那爲何還需要Kafka Strom呢,主要原因如下:

1.Spark 和 Strom是流式處理框架,而Kafak Stream是一個基於Kafka的流式處理類庫。 框架要求開發者按照特定的方式去開發邏輯,供框架調用。開發者很難了解框架的具體運行方式,從而使得調試成本高。Kafka Stream作爲一個流式處理類庫,直接提供具體的類給開發者調用,整個應用的運行方式主要由開發者調用。整個應用的運行方式有開發者控制

2.Kafka部署簡單

3.就流式處理而言,基本都支持Kafka作爲數據源。例如Strom有專門的kafka-spout,而Spark也提供專門的spark-kafka-stream模塊。事實上,kafka基本上是主流的流式處理標準數據源。大部分流失系統中都已經部署了Kafka,此時使用Kafka的成本非常低。

4.由於Kafka本身提供數據持久化,因此Kafka Stream提供滾動部署和滾動升級以及重新計算的能力。

5.由於Kafka的Consumer的Rebanace機制,Kafka可以在線動態調整並行度。

Processor Topology

        基於kafka stream的流式應用邏輯全部通過一個被稱爲Processor Topology的地方執行。它與strom的Topology和Spark的DAG類似。都定義了數據在各個處理單元間的流動方式,或者說定義了數據的處理邏輯。

public class WordCountProcessor implements Processor<String, String> {
  private ProcessorContext context;
  private KeyValueStore<String, Integer> kvStore;
  @SuppressWarnings("unchecked")
  @Override
  public void init(ProcessorContext context) {
    this.context = context;
    this.context.schedule(1000);
    this.kvStore = (KeyValueStore<String, Integer>) context.getStateStore("Counts");
  }
  @Override
  public void process(String key, String value) {
    Stream.of(value.toLowerCase().split(" ")).forEach((String word) -> {
      Optional<Integer> counts = Optional.ofNullable(kvStore.get(word));
      int count = counts.map(wordcount -> wordcount + 1).orElse(1);
      kvStore.put(word, count);
    });
  }
  @Override
  public void punctuate(long timestamp) {
    KeyValueIterator<String, Integer> iterator = this.kvStore.all();
    iterator.forEachRemaining(entry -> {
      context.forward(entry.key, entry.value);
      this.kvStore.delete(entry.key);
    });
    context.commit();
  }
  @Override
  public void close() {
    this.kvStore.close();
  }
}

從上述代碼中可見:

1.processor定義了每條記錄的處理邏輯,也驗證了Kafka具有記錄級的數據處理能力。

2.context.scheduler定義了processor被執行的週期,從而提供了實現操作窗口的操作。

3.context.getStateStore提供的狀態存儲爲有狀態的計算(如窗口、聚合)提供了可能。

Kafka Strom的並行模型:

        並行模型中,最小粒度爲Task,而每個Task包含一個特定子Topology的所有Processor。因此每個Task所執行的代碼完全一樣,唯一的不同在於所處理的數據集互補。Kafka Stream的Task包含了完整的子Topology,所以Task之間不需要傳遞數據,也就不需要網絡通信。這一點降低了系統複雜度,也提供了系統處理效率。

KTable vs KStream 

KStream<String, String> stream = builder.stream("words-stream");
KTable<String, String> table = builder.table("words-table", "words-store");

KTable和KStream 是非常重要的兩個概念。他們是Kafka實現各種語義的基礎。因此這裏有必要分析一下二者的區別。

KStream是一個數據流,可以認爲所有記錄都通過insert only 的方式插入到進入這個數據流裏面。KTable代表一個完整的數據集,可以理解爲數據庫中的表。由於每條記錄都有Key-Value對,這裏可以將key理解爲數據庫中的Primary Key,而value可以理解爲一行記錄。可以認爲KTable中的數據都是通過update only方式進入的。也就意味着,如果KTable對應的Topic中新進入的數據Key已經存在。那麼KTable自會取出同一個Key對應的最後一條記錄,相當於新的數據更新了舊的數據。

State Store

        流式處理中,部分操作是無狀態的。例如操作過濾,而部分操作是有狀態的,需要記錄中間狀態,如Windows操作和聚合操作。State Store被用來存儲中間狀態。他可以是一個持久化的key-value存儲,也可以是內存中的HashMap或者數據庫。Kafka提供了基於Topic的狀態存儲。

       Topic中存儲的數據本身是key-value形式的,同時Kafka的log commpacting機制對歷史數據做compact,保留每個key的最後一個value,從而在key不丟失的情況下,減少數據總量。提升查詢效率。

       構造KTable時候,需要制定其state store name.默認情況下,該名字也即用於存儲該KTable的狀態的Topic的名字。遍歷KTable的過程,實際就是遍歷它對應的state store,或者遍歷Topic的所有key。

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