MapReduce的大致流程:
1、HDFS讀取數據;
2、按照規則進行分片,形成若干個spilt;
3、進行Map
4、打上分區標簽(patition)
5、數據入環形緩沖區(KVbuffer)
6、原地排序,并溢寫(sort+spill)
7、combiner+merge,落地到磁盤
8、shuffle到reduce緩存
9、繼續歸并排序(mergesotr)
10、reduce
11、輸出到HDFS
解剖環形緩沖區:
環形緩沖區解釋:環形緩沖區分為三塊,空閑區、數據區、索引區。初始位置取名叫做“赤道”,就是圓環上的白線那個位置。初始狀態的時候,數據和索引都為0,所有空間都是空閑狀態。
tips:這里有一個調優參數,可以設置環形緩沖區的大小:
mapreduce.task.io.sort.mb,默認100M,可以稍微設置大一些,但不要太大,因為每個spilt就128M。
個人理解:因為環形緩沖區底層是一個數組
1、首先發生溢出時,Map溢出的數據會轉成byte字節,從兩側開始向中間寫入,一側寫入數據,一側寫入記錄的索引信息。
2、當溢出的數據量達到mapreduce.map.sort.spill.percent參數設置的比例時(默認80%,這個是調優的參數)之后,會從剩余的20%空間中選出一個新的“赤道”,后續Map的溢出數據,將從新的赤道向兩側寫入,一側寫入數據,一側寫入記錄的索引信息。
3、第二次寫入剩余的20%同時,會將第一次寫入的數據進行刷寫到磁盤中,由此過程循環往復,同時完成溢入-寫出的過程,且在主線程mr執行過程中,會產生多次溢寫操作,每次溢寫都會產生溢寫文件,整個操作都在內存,形狀像一個環,所以才叫環形緩沖區。
4、完整實現圖
為什么要有環形緩沖區?
我們讀取到文件,直接排序,然后寫到HDFS里不就好了嗎?為啥還要整一個環形緩沖區呢?
那從架構的角度看環形緩沖區,他這么設計有什么用呢?解決什么問題呢?
思路廣的朋友應該已經反應過來了。環形緩沖區不需要重新申請新的內存,始終用的都是這個內存空間。大家知道MR是用java寫的,而Java有一個最討厭的機制就是Full GC。Full GC總是會出來搗亂,這個bug也非常隱蔽,發現了也不好處理。環形緩沖區從頭到尾都在用那一個內存,不斷重復利用,因此完美的規避了Full GC導致的各種問題,同時也規避了頻繁申請內存引發的其他問題。
另外呢,環形緩沖區同時做了兩件事情:1、排序;2、索引。在這里一次排序,將無序的數據變為有序,寫磁盤的時候順序寫,讀數據的時候順序讀,效率高非常多!
在這里設置索引區也是為了能夠持續的處理任務。每讀取一段數據,就往索引文件里也寫一段,這樣在排序的時候能加快速度。
更多的詳細信息你可以參考《Hadoop技術內幕:深入解析MapReduce架構設計與實現原理 》