Storm系列(四)並行度和流分組

codeing_docs發表於2019-01-06

原文連線:a870439570.github.io/interview-d…

並行度(parallelism)概念

  • 一個執行中的拓撲是由什麼構成的:工作程式(worker processes),執行器(executors)和任務(tasks)
  • 在 Worker 中執行的是拓撲的一個子集。一個 worker 程式是從屬於某一個特定的拓撲的,在 worker 程式中會執行一個或者多個與拓撲中的元件相關聯的 executor。一個執行中的拓撲就是由這些執行於 Storm叢集中的很多機器上的程式組成的。
  • 一個 executor 是由 worker 程式生成的一個執行緒。在 executor 中可能會有一個或者多個 task,這些 task 都是為同一個元件(spout 或者 bolt)服務的。
  • task 是實際執行資料處理的最小工作單元(注意,task 並不是執行緒) —— 在你的程式碼中實現的每個 spout 或者 bolt 都會在叢集中執行很多個 task。在拓撲的整個生命週期中每個元件的 task 數量都是保持不變的,不過每個元件的 executor數量卻是有可能會隨著時間變化。在預設情況下 task 的數量是和 executor 的數量一樣的,也就是說,預設情況下 Storm會在每個執行緒上執行一個 task。

Storm的流分組策略

  • Storm的分組策略對結果有著直接的影響,不同的分組的結果一定是不一樣的。其次,不同的分組策略對資源的利用也是有著非常大的不同
  • 拓撲定義的一部分就是為每個Bolt指定輸入的資料流,而資料流分組則定義了在Bolt的task之間如何分配資料流。

八種流分組定義

Shuffle grouping:

  • 隨機分組:隨機的將tuple分發給bolt的各個task,每個bolt例項接收到相同數量的tuple。

Fields grouping:

  • 按欄位分組:根據指定的欄位的值進行分組,舉個栗子,流按照“user-id”進行分組,那麼具有相同的“user-id”的tuple會發到同一個task,而具有不同“user-id”值的tuple可能會發到不同的task上。這種情況常常用在單詞計數,而實際情況是很少用到,因為如果某個欄位的某個值太多,就會導致task不均衡的問題。

Partial Key grouping:

  • 部分欄位分組:流由分組中指定的欄位分割槽,如“欄位”分組,但是在兩個下游Bolt之間進行負載平衡,當輸入資料歪斜時,可以更好地利用資源。優點。有了這個分組就完全可以不用Fields grouping了

All grouping:

  • 廣播分組:將所有的tuple都複製之後再分發給Bolt所有的task,每一個訂閱資料流的task都會接收到一份相同的完全的tuple的拷貝。

Global grouping:

  • 全域性分組:這種分組會將所有的tuple都發到一個taskid最小的task上。由於所有的tuple都發到唯一一個task上,勢必在資料量大的時候會造成資源不夠用的情況。

None grouping:

  • 不分組:不指定分組就表示你不關心資料流如何分組。目前來說不分組和隨機分組效果是一樣的,但是最終,Storm可能會使用與其訂閱的bolt或spout在相同程式的bolt來執行這些tuple

Direct grouping:

  • 指向分組:這是一種特殊的分組策略。以這種方式分組的流意味著將由元組的生成者決定消費者的哪個task能接收該元組。指向分組只能在已經宣告為指向資料流的資料流中宣告。tuple的發射必須使用emitDirect種的一種方法。Bolt可以通過使用TopologyContext或通過在OutputCollector(返回元組傳送到的taskID)中跟蹤emit方法的輸出來獲取其消費者的taskID。

Local or shuffle grouping: 本地或隨機分組:和隨機分組類似,但是如果目標Bolt在同一個工作程式中有一個或多個任務,那麼元組將被隨機分配到那些程式內task。簡而言之就是如果傳送者和接受者在同一個worker則會減少網路傳輸,從而提高整個拓撲的效能。有了此分組就完全可以不用shuffle grouping了。

示例

修改上一章節的Topology Storm(三)Java編寫第一個本地模式demo

package com.qxw.topology;
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;

import com.qxw.bolt.OutBolt;
import com.qxw.bolt.OutBolt2;
import com.qxw.spout.DataSource;

/**
 * 拓撲的並行性
 * @author qxw
 * @data 2018年9月17日下午2:49:09
 */
public class TopologyTest2 {

	public static void main(String[] args) throws Exception {
		//配置
		Config cfg = new Config();
		cfg.setNumWorkers(2);//指定工作程式數  (jvm數量,分散式環境下可用,本地模式設定無意義)
		cfg.setDebug(false);
		
		//構造拓撲流程圖
		TopologyBuilder builder = new TopologyBuilder();
		//設定資料來源(產生2個執行器和倆個任務)
		builder.setSpout("dataSource", new DataSource(),2).setNumTasks(2);
		//設定資料建流處理元件(產生2個執行器和4個任務)
		builder.setBolt("out-bolt", new OutBolt(),2).shuffleGrouping("dataSource").setNumTasks(4); //隨機分組
		//設定bolt的並行度和任務數:(產生6個執行器和6個任務)
//		builder.setBolt("out-bol2", new OutBolt2(),6).shuffleGrouping("out-bolt").setNumTasks(6); //隨機分組
		
		//設定欄位分組(產生8個執行器和8個任務)欄位分組 
		builder.setBolt("out-bol2", new OutBolt2(),8).fieldsGrouping("out-bolt", new Fields("outdata")).setNumTasks(8);
		//設定廣播分組
		//builder.setBolt("write-bolt", new OutBolt2(), 4).allGrouping("print-bolt");
		//設定全域性分組
		//builder.setBolt("write-bolt", new OutBolt2(), 4).globalGrouping("print-bolt");
		
		//1 本地模式
		LocalCluster cluster = new LocalCluster();
		
		//提交拓撲圖  會一直輪詢執行
		cluster.submitTopology("topo", cfg, builder.createTopology());

		
		//2 叢集模式
//		StormSubmitter.submitTopology("topo", cfg, builder.createTopology());
		
	}
}

}

複製程式碼

相關文章