Flink 的廣播變量

Flink 支持廣播變量,就是將數據廣播到具體的 taskmanager 上,數據存儲在內存中,這樣可以減緩大量的 shuffle 操作;

比如在數據 join 階段,不可避免的就是大量的 shuffle 操作,我們可以把其中一個 dataSet 廣播出去,一直加載到 taskManager 的內存中,可以直接在內存中拿數據,避免了大量的 shuffle,導致集羣性能下降;

廣播變量創建後,它可以運行在集羣中的任何 function 上,而不需要多次傳遞給集羣節點。另外需要記住,不應該修改廣播變量,這樣才能確保每個節

點獲取到的值都是一致的。

一句話解釋,可以理解爲是一個公共的共享變量,我們可以把一個 dataset數據集廣播出去,然後不同的 task 在節點上都能夠獲取到,這個數據在每個節

點上只會存在一份。如果不使用 broadcast,則在每個節點中的每個 task 中都需要拷貝一份 dataset 數據集,比較浪費內存(也就是一個節點中可能會存在多份dataset 數據)。

注意:因爲廣播變量是要把 dataset 廣播到內存中,所以廣播的數據量不能太大,否則會出現 OOM 這樣的問題

  • Broadcast:Broadcast 是通過 withBroadcastSet(dataset,string)來註冊的
  • Access:通過 getRuntimeContext().getBroadcastVariable(String)訪問廣播變量

操作步驟

1:初始化數據
DataSet<Integer> toBroadcast = env.fromElements(1, 2, 3)
2:廣播數據
.withBroadcastSet(toBroadcast, "broadcastSetName");
3:獲取數據
Collection<Integer> broadcastSet = getRuntimeContext().getBroadcastVariable("broadcastSetName");

例子:

package dh.flink.com.dataset.transform;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.java.DataSet;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.configuration.Configuration;

public class BroadCastTest {

    public static void main(final String[] args) throws Exception{
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        //1.封裝一個DataSet
        DataSet<Integer> broadcast = env.fromElements(1, 2, 3);
        
        DataSet<String> data = env.fromElements("a", "b");
        data.map(new RichMapFunction<String, String>() {
        	
            private List list = new ArrayList();
            
            @Override
            public void open(final Configuration parameters) throws Exception {
                // 3. 獲取廣播的DataSet數據 作爲一個Collection
            	//通過getRuntimeContext().getBroadcastVariable(String)訪問廣播變量
                Collection<Integer> broadcastSet = getRuntimeContext().getBroadcastVariable("number");
                list.addAll(broadcastSet);
            }

            @Override
            public String map(final String value) throws Exception {
                return value + ": "+ list;
            }
            
        }).withBroadcastSet(broadcast, "number") //Broadcast是通過withBroadcastSet(dataset,string)來註冊的
            // 2. 廣播的broadcast
          .printToErr();//打印到err方便查看
    }
}
package dh.flink.com.dataset.transform.guangbo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.java.DataSet;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.operators.DataSource;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;

/**
 * 廣播
 * 
 * @author duhai
 * @date 2020年1月10日
 */
public class BatchDemoBroadcast {

	public static void main(final String[] args) throws Exception {

		// 獲取運行環境
		ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();

		// 1:準備需要廣播的數據
		ArrayList<Tuple2<String, Integer>> broadData = new ArrayList<Tuple2<String, Integer>>();
		broadData.add(new Tuple2<String, Integer>("zs", 18));
		broadData.add(new Tuple2<String, Integer>("ls", 20));
		broadData.add(new Tuple2<String, Integer>("ww", 17));
		DataSet<Tuple2<String, Integer>> tupleData = env.fromCollection(broadData);

		// 1.1:處理需要廣播的數據,把數據集轉換成map類型,map中的key就是用戶姓名,value就是用戶年齡
		DataSet<HashMap<String, Integer>> toBroadcast = tupleData
				.map(new MapFunction<Tuple2<String, Integer>, HashMap<String, Integer>>() {
					public HashMap<String, Integer> map(final Tuple2<String, Integer> value) throws Exception {
						HashMap<String, Integer> res = new HashMap<String, Integer>();
						res.put(value.f0, value.f1);
						return res;
					}
				});

		// 源數據
		DataSource<String> data = env.fromElements("zs", "ls", "ww");

		// 注意:在這裏需要使用到RichMapFunction獲取廣播變量
		DataSet<String> result = data.map(new RichMapFunction<String, String>() {

			List<HashMap<String, Integer>> broadCastMap = new ArrayList<HashMap<String, Integer>>();
			HashMap<String, Integer> allMap = new HashMap<String, Integer>();

			/**
			 * 這個方法只會執行一次 可以在這裏實現一些初始化的功能。所以,就可以在open方法中獲取廣播變量數據
			 *
			 */
			@Override
			public void open(final Configuration parameters) throws Exception {
				super.open(parameters);
				// 3:獲取廣播數據
				this.broadCastMap = getRuntimeContext().getBroadcastVariable("broadCastMapName");
				for (HashMap map : broadCastMap) {
					allMap.putAll(map);
				}

			}

			@Override
			public String map(final String value) throws Exception {
				Integer age = allMap.get(value);
				return value + "," + age;
			}
		}).withBroadcastSet(toBroadcast, "broadCastMapName");// 2:執行廣播數據的操作
		result.print();
	}
}

 

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