# hadoop https://hackmd.io/@QI-AN/rk4cq0M5q 資訊科技 (Infomation Technology) ![](https://i.imgur.com/x2Tc6q6.png) * 「Business Intelligence」商業智慧:就是為了要做出決策報告。 * Business Intelligence世界第一品牌 teradata。 * 現在的公司使用資料庫就是為了能夠分析出有效、有價值的決策報告,但是teradata天睿這家公司出版的Teradata資料庫,不只軟體價格變高,還要求使用指定的硬體設備,讓很多公司受不了。 * OLTP的資料會抓去OTAP做備份 * binlog:他會儲存備份資料 * CDC:他會一直去抓binlog的資料 * Data Warehouse:把已經備份好的資料再給他很多種的model做出資料庫,主要是為了Business Intelligence。 ![](https://i.imgur.com/1oHmsiU.png) * 因為teradata太貴了,所以另一個替代方案就是使用Hadoop。 * 另外一個替代方案以Hadoop搭配Hive,就可以做出企業所需要的Business Intelligence。 * Hadoop 儲存資料的單位以T來計算,他本身不提供修改功能。 * Hive架在hadoop之上,hive主要就是來做商業智慧的分析,所以他不是用來資訊的管理(新增刪除)。 * Spark (machine learning):主要是做資料深度分析,用來預測開發。 * HBase:用來處理iot,他是架在hadoop之上,有新增刪除修改的功能。 * 五顆寶石(資料來源): 1. 拇指圖案(OLAP):把企業的資料丟到hadoop。 2. 星星圖案(opendate):政府資料開放平台。 3. 放大鏡圖案(爬蟲程式):利用程式去抓程式,但是爬蟲回來的資料可用度不高。 4. 計算機圖案:要取得某個工廠的資料,需要取得法規的許可,並且人際關係要夠好,雖然都是同個公司,但是資料並不互通。 5. intel圖案(黑暗面):就是買資料。 ## hadoop架構 ![](https://i.imgur.com/RquL4E0.png) * Hadoop Distributed File System (HDFS™),分散式檔案系統,這套檔案系統在運作一定要多台電腦 > windows的檔案系統為:NTFS * YARN,運算系統,專門來跑程式的,就是分析儲存的資料,可以平行處理,意思就是說可以在多台電腦同時讓Mapreduce和Spark跑程式分析資料 > Hadoop算不算一個資料型的作業系統? > 是,因為它具備資料儲存、運算能力 > windows裡,執行程式的平台叫做. net,其中有一個msSQ * MapReduce,內建資料處理引擎,用來做資料分析 Spark,(可加裝)也是資料處理引擎 Hive,會使用MapReduce做出來的分析 Hadoop Common: The common utilities that support the other Hadoop modules. 代表Hadoop的管理命令和應用命令 ![](https://i.imgur.com/r7fVLsP.png) * hadoop一定是多台電腦用java程式做出來的。 * hadoop有六台電腦,dta1做管理主機,dtm1:namenode,dtm2:resource manager (yarn主要的管理程式),dtw1,dtw2,dtw3:datanode。 * dtm1:上有NameNode,還有Secondary NameNode,他們就是java程式。 * dtw1 dtw2 stw3:data node,工作機。 * dtm2:resource manager,也都是jave程式。 ## HDFS 分散檔案系統 - 寫入檔案 ![](https://i.imgur.com/wvTj9mA.png) * client就是代表dta1,操作這台電腦的人就是資料管理師,他會上網去下載 `wget http://a.b.c/File.txt`再把檔案丟到hdfs檔案系統`hdfs dfs -put File.txt mydataset`,他會把file.txt切成三個區塊blk(block) * 只要檔案要丟到hdfs,他在本機一定要先做切割。 * 切割的方法,每128m為單位 > 問題:一個檔案128m,那三個檔案檔案總共多大? > 答:檔案的大小一定不會剛好,他會是一個範圍,因此有三個block,第三個block的大小我們不確定因此範圍是256m<x<=384m dta1 把資料做切割後,會問name node要把block放在哪裡,因為現在有三個block,所以會放在三台電腦。 * 只要檔案往hdfs檔案系統丟,檔案一定會被切成很多個block,除非那個檔案很小;之後client會去找name node(HDFS),name node會安排每一個block要存在哪三台datanode機器裡面(一個block要存在三台不同的datanode主機)。 - 切割方法:128mb為單位(hadoop內定預設值),只要超過一個byte就會被多切一個block出來。 - 一個block內定一定存在三台不同的data node主機。 - 如果存1g大小的檔案,在hdfs檔案系統就等於存3g的檔案大小 * data node 1(dtw1) 收到blk a後,dtw1資料存到64k後就會開始把資料傳給dtw5(dtw1會持續把資料收完),一樣dtw5資料收到64k後會開始把檔案傳給dtw6,雖然檔案沒收完就傳給下一台主機,但檔案最終一定都會收完(同步的概念)。 - 如果一台data node掛了,我們還是可以讀到File.txt檔案,hdfs有容錯的能力。 ## HDFS 分散檔案系統 - 讀取檔案 ![](https://i.imgur.com/ViecfRK.png) * client想要看檔案,name node會告訴他這三個blk分別放在哪,他會列出一個清單,並且取第一順位的blk,例如: * blk A = 1、5、6 * blk B = 8、1、2 * blk C = 5、8、9 * (他會取1、8、5這三個data node)告訴dta1,知道位置後這三個blk會同時傳給dta1,然後再把三個blk合成一個我們要看檔案。 - name node列出的清單順序,如果同時有不同的人來讀同一個檔案,那每個人name node列出的清單(data node會不同)都會不一樣,這就是round robin(循環制)。 「HDFS好處」 1. 檔案切塊分散三台機器儲存,可容錯 2. 分散儲存檔案要讀取時由三台機器提供各自儲存的檔案,讀取效率高 3. 多人共用時會有round robin 的概念,輪流由不同組合機器提供檔案 > 問題:如果hadoop一個檔案是100t,那client可以讀到檔案嗎? > 答:因為client的電腦設備一定不是機房的規格,硬碟不夠大,那client一定讀不進來。 > 問題:承上題,那要如何處理這個問題? > 答:由後端的那些電腦(dtw1,dtw2...)來做資料分析,就是MapReduce,這是hadoop內建的資料處理引擎。 ## HDFS 系統資訊 ``` ##可以看到hdfs架構的駐點資訊 $ hdfs dfsadmin -report Configured Capacity: 1582106935296 (1.44 TB) ##多少空間可以使用 Present Capacity: 1465391128576 (1.33 TB) DFS Remaining: 1465384878080 (1.33 TB) DFS Used: 6250496 (5.96 MB) DFS Used%: 0.00% Replicated Blocks: Under replicated blocks: 0 Blocks with corrupt replicas: 0 Missing blocks: 0 Missing blocks (with replication factor 1): 0 Pending deletion blocks: 0 Erasure Coded Block Groups: Low redundancy block groups: 0 Block groups with corrupt internal blocks: 0 Missing block groups: 0 Pending deletion blocks: 0 ------------------------------------------------- Live datanodes (3): ##活者的datanode有幾台 Name: 192.168.61.6:9866 (dtw1) Hostname: dtw1 Decommission Status : Normal Configured Capacity: 526185201664 (490.05 GB) ##dtw1可用的空間 DFS Used: 84848640 (80.92 MB) Non DFS Used: 6600155136 (6.15 GB) DFS Remaining: 492696236032 (458.86 GB) ............ ............ ``` * 檔案的名字、檔案的資訊、屬性,都會存在name node這支java的程式裡,也就是dtm1主機。 * mate data :File name(名稱),File attributes(屬性) * 檔案的資料是分散在不同的 data node 主機 ## Name Node 目錄內容 ``` ##namenode這個java程式負責存hdfs的matedata ##nn這個目錄會存hdfs的mate data ##這裡會紀錄hdfs的檔案系統目錄,還有檔案屬性(檔案名稱,檔案的權限) ## edites 存放hadoop下達過的指令: hdfs dfs -put -cat... ## fsimage 紀錄檔案系統(檔案,目錄的資訊) ## 所以其實HDFS檔案系統是以Linux為基礎建設出來的 ##dtm1負責儲存檔案存放的位置 $ ssh dtm1 tree nn nn ├── current │ ├── VERSION │ ├── edits_0000000000000000001-0000000000000000009 │ ├── edits_0000000000000000010-0000000000000000011 │ ├── edits_inprogress_0000000000000000012 │ ├── fsimage_0000000000000000000 ##hdfs檔案系統的mate data │ ├── fsimage_0000000000000000000.md5 ##mate data身分證號碼,防止mate data被竄改 │ └── seen_txid └── in_use.lock 1 directory, 10 files $ ssh dtm1 cat nn/current/VERSION #Thu Nov 08 02:31:28 GMT 2018 namespaceID=1539483458 clusterID=cute cTime=1541644288235 storageType=NAME_NODE blockpoolID=BP-564818905-172.30.0.10-1541644288235 ##name node跟data node靠這個id做溝通 layoutVersion=-64 ``` ## Data Node 目錄內容 ``` ## dn就是linux的目錄,所以data node也是用linux的檔案系統來做他要處理的資料 ##blk就是放在這個dn目錄區 $ ssh dtw1 tree dn dn ├── current │ ├── BP-1785240759-192.168.61.4-1645624914539 ## name node的識別代號,目前這個data node為這個name node服務 │ │ ├── current │ │ │ ├── dfsUsed │ │ │ ├── finalized │ │ │ │ └── subdir0 │ │ │ │ └── subdir0 ##各種blk │ │ │ │ ├── blk_1073741829 │ │ │ │ ├── blk_1073741829_1009.meta │ │ │ │ ├── blk_1073741830 │ │ │ │ ├── blk_1073741830_1010.meta │ │ │ │ ├── blk_1073741831 │ │ │ │ └── blk_1073741831_1011.meta │ │ │ ├── rbw │ │ │ └── VERSION │ │ ├── scanner.cursor │ │ └── tmp │ └── VERSION └── in_use.lock ``` ## 檢視 NameNode MetaData 立即更新 fsimage ``` ## 換成安全模式,只能讀目錄和讀檔案,不能新增和刪除檔案 $ hdfs dfsadmin -safemode enter Safe mode is ON ##他會更新fsimage ##他會把新的metadata存在這裡 $ hdfs dfsadmin -saveNamespace Save namespace successful [註] 會立即將記憶體中的資料寫入一個新的 fsimage 檔中 $ ssh dtm1 tree -sh nn .......... │ ├── edits_inprogress_0000000000000000012 │ ├── fsimage_0000000000000000000 │ ├── fsimage_0000000000000000000.md5 │ ├── fsimage_0000000000000000011 │ ├── fsimage_0000000000000000011.md5 .......... ##關閉安全模式 $ hdfs dfsadmin -safemode leave Safe mode is OFF ``` 取出 fsimage 檔, 並將之轉換成 csv 格式檔 ``` ## 在dtm1拷貝到/tmp目錄裡 ##-fetchImage 抓剛剛最新的metadata檔案 $ hdfs dfsadmin -fetchImage /tmp/ $ dir /tmp/fsimage* -rw-rw-r-- 1 bigred bigred 320 7月 15 20:21 /tmp/fsimage_0000000000000000020 HDFS Offline Image Viewer ## 把fsimage這個matedata檔案換成csv格式 $ hdfs oiv -i /tmp/fsimage_0000000000000000020 -o /tmp/fsimage.csv -p Delimited -delimiter "," ``` ``` ##可以看到整個metadata資訊,使用者,檔案權限目錄,創建時間,資料都寫在這裡 $ cat /tmp/fsimage.csv Path,Replication,ModificationTime,AccessTime,PreferredBlockSize,BlocksCount,FileSize,NSQUOTA,DSQUOTA,Permission,UserName,GroupName /,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,9223372036854775807,-1,drwxr-xr-x,bigred,bigboss /tmp,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwx---,bigred,bigboss /tmp/hadoop-yarn,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwx---,bigred,bigboss /tmp/hadoop-yarn/staging,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwx---,bigred,bigboss /tmp/hadoop-yarn/staging/history,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwx---,bigred,bigboss /tmp/hadoop-yarn/staging/history/done,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwx---,bigred,bigboss /tmp/hadoop-yarn/staging/history/done_intermediate,0,2022-02-23 22:02,1970-01-01 08:00,0,0,0,-1,-1,drwxrwxrwt,bigred,bigboss ``` [註] NameNode MetaData 只存放 目錄與檔案 資訊, 沒有 Transaction 資訊, Transaction 資訊分存在 edits_xxxxx 這類檔中 ## HDFS 容錯處理 - 遺失資料區塊 ``` ##把我們linux的帳號檔案丟到hdfs裡面 $ hdfs dfs -put /etc/passwd /tmp/ ##這個檔案只有1.5k,所以只有一個block $ ls -lh /etc/passwd -rw-r--r-- 1 root root 1.5K Sep 13 12:05 /etc/passwd ##找這個BLK在哪裡 ##blk_1073741845_1021 blk名稱 ##192.168.61.6、192.168.61.7 這個blk存在這兩個data node(這邊只有兩個是因為老師設定的) bigred@dtm1:~$ hdfs fsck /tmp/passwd -files -blocks -locations Connecting to namenode via http://dtm1:9870/fsck?ugi=bigred&files=1&blocks=1&locations=1&path=%2Ftmp%2Fpasswd FSCK started by bigred (auth:SIMPLE) from /192.168.61.4 for path /tmp/passwd at Tue Jul 26 14:52:46 CST 2022 /tmp/passwd 1426 bytes, replicated: replication=2, 1 block(s): OK 0. BP-727742586-192.168.61.4-1658817601466:blk_1073741845_1021 len=1426 Live_repl=2 [DatanodeInfoWithStorage[192.168.61.6:9866,DS-1248c60c-51da-451a-9252-a8245868d702,DISK], DatanodeInfoWithStorage[192.168.61.7:9866,DS-0639480e-2155-4377-983b-667fdff6061f,DISK]] ``` ``` ##刪除blk $ rm dn/current/BP-727742586-192.168.61.4-1658817601466/current/finalized/subdir0/subdir0/blk_1073741845* ``` ``` 還是可以看得到檔案 $ hdfs dfs -cat /tmp/passwd root:x:0:0:root:/root:/bin/ash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin ....... ``` ``` ## 同一個blk又回復了 $ tree dn dn ├── current │   ├── BP-727742586-192.168.61.4-1658817601466 │   │   ├── current │   │   │   ├── VERSION │   │   │   ├── finalized │   │   │   │   └── subdir0 │   │   │   │   └── subdir0 │   │   │   │   ├── blk_1073741836 │   │   │   │   ├── blk_1073741836_1012.meta │   │   │   │   ├── blk_1073741837 │   │   │   │   ├── blk_1073741837_1013.meta │   │   │   │   ├── blk_1073741844 │   │   │   │   ├── blk_1073741844_1020.meta │   │   │   │   ├── blk_1073741845 │   │   │   │   └── blk_1073741845_1021.meta ``` > 結論:把blk刪除,在下hdfs dfs -cat,還是可以看得到檔案,資料還原了 * 如果把其中一個data node的blk刪除,這時候如果cat沒有到沒有被刪除的blk,那他就還不會被修復,所以這時候去tree dn(被刪掉blk的機器),他的檔案還是沒復原,解法:多cat幾次,讓系統讀到那個blk。 > 問題:為什麼我把全部的blk都刪除了,我還是看的到檔案名稱? > 答:因為檔案名稱是mate data,他是存在name node,他的檔案是放在dtm1。 ## HDFS 設定檔 ``` $ tree $HADOOP_HOME/etc/hadoop /opt/hadoop-3.3.3/etc/hadoop :: ├── core-site.xml ├── hadoop-env.sh ##hadoop要建起來要設定環境變數 ├── hdfs.allow (內定只允許 5 部工作主機) ├── hdfs-site.xml :: ├── mapred-site.xml :: ├── yarn-env.sh └── yarn-site.xml ``` 在dta1一定要有這個java程式,才能跑hadoop,因為我們環境變數有設定java所以我們可以直接跑這個程式 ``` $ java -version openjdk version "1.8.0-332" OpenJDK Runtime Environment (build 1.8.0-332-b09) OpenJDK 64-Bit Server VM (build 25.71-b09, mixed mode) ``` 但是hadoop其實是靠這個設定檔找到java的程式,並不是在PATH找到的 ``` $ sudo nano $HADOOP_HOME/etc/hadoop/hadoop-env.sh ....... export JAVA_HOME=/opt/openjdk-8u332-linux-x64 ....... export HADOOP_HEAPSIZE=512 ##hadoop所有程式能跑的記憶體大小 ........ export HADOOP_LOG_DIR=/tmp ##如果那些java程式有bug,都會丟到/tmp這個目錄 hadoop java 程式: NameNode DataNode SecondaryNameNode JobHistoryServer ResourceManager NodeManager [註] Java 7 was end-of-lifed in April 2015, meaning Oracle would no longer publicly support it with security fixes. ``` * 設定hdfs > xml 主要是用來做系統設定的格式,html主要是做顯示,雖然他們的格式有點像,但他們功能差很多 ``` $ sudo nano $HADOOP_HOME/etc/hadoop/hdfs-site.xml <?xml version="1.0" encoding="UTF-8"?> ......... <configuration> <property> <name>dfs.replication</name> <value>3</value> ##這邊3代表每一個blk存3分,如果沒有特定去調整內定都是3 </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/home/bigred/nn</value> ##設定matedata存在nn目錄 </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/home/bigred/dn</value> ##datanode存blk是在dn這個目錄區 </property> <property> <name>dfs.permissions.superusergroup</name> <value>bigboss</value> ##管理者群組名稱 </property> ........... </configuration> ``` [註] 在 client 端 (dta1) 修改 dfs.replication 數值後, 不需重新啟動 HDFS 分散檔案系統, 設定值直接生效 * hadoop核心設定 ``` $ sudo nano $HADOOP_HOME/etc/hadoop/core-site.xml <?xml version="1.0" encoding="UTF-8"?> ........ <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://dtm1:8020</value> ##hadoop namenode要在哪裡執行,namenode port國際標準8020 </property> <property> <name>fs.default.name</name> <value>hdfs://dtm1:8020</value> ##可以連到舊的名稱 </property> <property> <name>io.compression.codecs</name> <value>org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.SnappyCodec</value> </property> ##hadoop用到的壓縮技術是BZip <property> <name>hadoop.user.group.static.mapping.overrides</name> <value>rbean=soup;gbean=soup,rice;ybean=rice</value> </property> </configuration> ``` ## YARN 分散運算系統(負責跑程式) ![](https://i.imgur.com/aLgZB0O.png) * Linux -> java(物件導向程式設計) -> JVM(process 程序),一定要有 JVM 來 run java,程序只要一起來就一定會霸佔記憶體空間。 * jvm會被載入到記憶體,記憶體裡面有分三個區域,static,stack,heap。 * 我們寫的程式,副檔名是(*.class),他會load到記憶體static區塊,變成一個表格叫blueprint(藍圖),最後做出object(物件)。 * java是由jvm去執行。 * 我們寫的java程式一定要有jvm,然後把她載入到記憶體,設計出藍圖,最後做出物件。 > windows -> C# -> .NET(他只會跑C#) > 也是一樣會把C#網記憶體裡面丟,然後去執行 > 結論:java大約等於C#,這倆個程式一定要有人去幫他執行(跟go還有c語言不一樣,這兩個是編譯完後作業系統就可以直接去執行他) * YARN跑的是mapreduce的java程式,還有Spark RDD的java程式,這類的資料引擎處理程式,其他的他不會。 ### 設定 YARN 總量運算資源 ![](https://i.imgur.com/qJPjt0A.png) * dtm2 中的 resource manager 認定一台機器有多少資源(CPU,記憶體)可以使用,是透過 dtw(1,2,3) 的 Node manager 告知 resource manager ,讓他知道現在這台工作機有多少硬體資源可以使用。 * 檢視 YARN 總量運算資源 ``` 在 dta1 執行以下命令 ##dtm2跑的是resource manager,問他有多少記憶體,CPU可以使用 $ curl -s http://dtm2:8088/ws/v1/cluster/metrics | jq | grep -E "totalMB|totalVirtualCores" "totalMB": 6144, "totalVirtualCores": 6, [重點] YARN 系統內定每部 Node Manager 的記憶體為 8G, CPU 為 8 Core ``` * 設定 YARN 總量運算資源 ``` ##設定 yarn ,記憶體修改3072,CPU改3 $ nano ~/vmalpdt/hdp33/conf/hadoop/yarn-site.xml ...... <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>3072</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>3</value> </property> ....... ``` 因為設定檔有改過,所以要在run這個命令把設定檔派送dtw1,dtw2,dtw3 `$ dtconf 33 ` * 3072*3因為有三台dtw1,dtw2,dtw3所以總量是9216 * 3*3因為有三台dtw1,dtw2,dtw3所以總量是9 ``` $ curl -s http://dtm2:8088/ws/v1/cluster/metrics | jq | grep -E "totalMB|totalVirtualCores" "totalMB": 9216, "totalVirtualCores": 9 ``` ## 設定 Container 可用運算資源 ![](https://i.imgur.com/zIsVSyG.png) 1. dtm1,dtm2裡面可以執行container。 2. node manager , resource manager,都是用 java 寫的,java 一定要有 jvm 去執行,他一定霸佔記憶體空間,在10幾年前又稱為 container,container 指的就是 JVM,因為 JVM 裡面裝 object,所以稱為容器。 * 一個container的運算資源設定 ``` ##記憶體要使用多少就要去問resource manager ##記憶體最少使用384,做多使用896 ##cpu只能使用一個核心 $ cat ~/vmalpdt/hdp33/conf/hadoop/yarn-site.xml ........ <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>384</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>896</value> </property> <property> <name>yarn.scheduler.minimum-allocation-vcores</name> <value>1</value> </property> <property> <name>yarn.scheduler.maximum-allocation-vcores</name> <value>1</value> </property> .......... ``` > 問題:在這個(記憶體:9216,CPU:9c)的資源下我們總共可以跑多少個container? > 答:9 個,cpu 和記憶體要一起考量,一個 container 最少要用 1 core,雖然記憶體不會用滿,但 cpu 已經用滿了,因此最多 9 個。 > 總共有三個 node manager ,因此一台 node manager 跑3個container ## 測試 YARN Container 最大的總執行量 ``` 在 dta1 終端機執行以下命令 $ startmaxctn ##15代表拿16個container來計算pi值 $ hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-${HADOOP_HOME##*-}.jar pi 15 300000 Number of Maps = 12 Samples per Map = 300000 Wrote input for Map #0 Wrote input for Map #1 ............ Wrote input for Map #8 Wrote input for Map #9 Wrote input for Map #10 Wrote input for Map #11 Starting Job Job Finished in 86.116 seconds Estimated value of Pi is 3.14163444444444444444 ``` ## 取得 YARN Container 最大的總執行量 * 因為我們是讓16個container一次去跑,他會有順序的去跑,同時最大量一定只有9個container ``` ##每一台機器在同一個時間點最多只有3個container,所以總共最多就是9個container $ stopmaxctn [dtw1] 10:19:19 -> Y:2 M:0 10:19:19 -> Y:3 M:0 10:19:27 -> Y:1 M:0 10:19:28 -> Y:1 M:0 10:19:29 -> Y:3 M:0 10:19:34 -> Y:2 M:0 10:19:35 -> Y:1 M:0 [dtw2] 10:19:08 -> Y:0 M:1 10:19:17 -> Y:1 M:1 10:19:18 -> Y:2 M:1 10:19:23 -> Y:1 M:1 10:19:25 -> Y:2 M:1 10:19:28 -> Y:1 M:1 10:19:29 -> Y:0 M:1 [dtw3] 10:19:19 -> Y:2 M:0 10:19:19 -> Y:3 M:0 10:19:27 -> Y:2 M:0 10:19:27 -> Y:1 M:0 10:19:28 -> Y:2 M:0 10:19:29 -> Y:3 M:0 10:19:34 -> Y:2 M:0 10:19:35 -> Y:1 M:0 ``` ## MapReduce 資料處理引擎 * YARN 分散運算系統運作圖 ![](https://i.imgur.com/sgPdJsd.png) * client 就是 dta1,他會寫 MapReduce(Java) 程式。 * Hive -> MapReduce(Java),hive 會幫忙寫 MapReduce 這支 java 程式。 * 寫好的程式會丟給 resource manager ,那他要去 run 程式,resource manager 會去找 node manager,請他啟動 container,container 裡面的程式叫做 app master 。 * app master 這隻程式的功能會決定要有多少個 Map 程式,還有幾個 Reduce 程式,他會去跟 resource manager 要求。 * 之後 resource manager 會再去找 node manager , 誰去執行 map 程式,誰去執行 reduce 程式。 * 資料的分析還有處理都會跟 app master 做報告。 * MAP 擷取、過濾。 * REDUCE 分析、把資料儲存到HDFS。 ## 檢視 MapReduce Job 的運算資源 在 dta1 終端機執行以下命令 ``` $ startjps # 2 代表現在要啟動三個 container # 啟動兩個 map 程式和一個 reduce 程式 $ yarn jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-${HADOOP_HOME##*-}.jar pi 2 100000 Number of Maps = 2 Samples per Map = 100000 Wrote input for Map #0 Wrote input for Map #1 Starting Job Job Finished in 25.829 seconds Estimated value of Pi is 3.14280000000000000000 ``` [註] map 及 樣本數 越大, PI 值越精準 ### 檢視 MapReduce Job 的運算資源 ``` # 要稱為大數據就是要能夠在多台電腦同時處理分析資料 # 第一個跑的一定是 app master # 總共有兩個 map ,一個 reduce # 一定會先啟動完 map ,再啟動 reduce # reduce 的記憶體大小是 384m $ stopjps [dtw1] [dtw2] 11:15:30 51020 YarnChild 256m # 51020 就是 pid ,他跑的是 map 程式 [dtw3] 11:15:23 50291 MRAppMaster 256m # 在 dtw3 第一個執行的 java 程式 11:15:30 50291 MRAppMaster 256m # 同一個 app master 51174 YarnChild 256m # 他就是 container 裡面跑的就是 map 11:15:33 50291 MRAppMaster 256m 11:15:36 50291 MRAppMaster 256m 51978 YarnChild 384m # 他跑的是 reduce 11:15:39 50291 MRAppMaster 256m ``` ## Mapreduce 運作架構圖 ![](https://i.imgur.com/8VKFpzk.png) * 土黃色的方塊:就是一個 block。 * block 存在的機器會啟動一個程式,map(也就是yarnchild)。 * map 可以同時在不同的機器同時執行,效能一定好,因為 hdfs 會把一個檔案切成很多 block。 * map:擷取與過濾資料。針對同一個檔案的不同 block。 * 每一個 map 都會產生小白區塊。 * shuffle 會把每一個小白區快 merged 成大白區塊,然後交給 reduce。 * merged:會把資料做分類跟排序。之後就產生大白資料。 * reduce:程式分析資料。分析好資料後會把檔案丟回 hdfs。 * 以上就是 MapReduce 資料處理引擎。 * 一個檔案切成多 block 好處: - 因為大數據資料檔案一定很大,因此切成多區塊,在讀資料的時候會同時讀所有的 block 多台電腦同時共同作業(分散運算),因此速度一定快。 - 平衡附載。 * 一個檔案同一個 block 存成三份的好處: - 可以有資料的容錯,並且有資料修復的功能,如果只有其中一個 block 被刪除,那這個 block 還可以被復原。 ### 設定 MapReduce Job 的運算資源 ```=! $ cat $HADOOP_HOME/etc/hadoop/mapred-site.xml .......... <property> <name>mapreduce.reduce.memory.mb</name> <value>512</value> # reduce 整個程式使用 512 記憶體大小,這個大小包含處理資料的記憶體大小 </property> <property> <name>mapreduce.reduce.java.opts</name> <value>-Xmx384m</value> # reduce 處理資料用的記憶體大小 </property> <property> <name>mapreduce.map.memory.mb</name> <value>384</value> # map 整個程式記憶體,這個大小包含處理資料的記憶體大小 </property> <property> <name>mapreduce.map.java.opts</name> <value>-Xmx256m</value> # map 處理資料的記憶體大小 </property> ........ ``` [註] 一般 reduce 設定為 map 的兩倍。Just make sure you set java.opts to 20-25% less than memory.mb > 問題:為什麼 reduce 的記憶體空間比較大, map 比較小? > 答:因為 map 要處理的 block 最大也只有 128m ,而 reduce 要做的是整個檔案的資料分析,因此一定比較大 ### 設定 MapReduce Job 運算資源 設定 reduce 記憶體需求, 只需修改 dta1 主機的 mapred-site.xml 設定檔 ``` $ sudo nano $HADOOP_HOME/etc/hadoop/mapred-site.xml ........ <property> <name>mapreduce.reduce.memory.mb</name> <value>1024</value> # 修改為 1024 </property> <property> <name>mapreduce.reduce.java.opts</name> <value>-Xmx896m</value> # 修改為 896 </property> ........ ``` ### 設定 MapReduce Job 運算資源 ```! # 測試 $ yarn jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-${HADOOP_HOME##*-}.jar pi 2 100000 ............ ...... reduceResourceRequest: <memory:1024, vCores:1> maxContainerCapability:<memory:896, vCores:1> Job received Kill while in RUNNING state. ``` * [註] 因 YARN 的 YARNChild 最大記憶體為 896M, 無法滿足 reduce 的要求, 使用 hadoop jar 命令執行上述運算, 如執行失敗, 不會出現錯誤訊息 ``` $ sudo nano $HADOOP_HOME/etc/hadoop/mapred-site.xml ........ <property> <name>mapreduce.reduce.memory.mb</name> <value>512</value> </property> <property> <name>mapreduce.reduce.java.opts</name> <value>-Xmx384m</value> </property> ........ ``` ![](https://i.imgur.com/uezM2yI.png) * Node Manager 會把自己有多少硬體資源告訴 Resource Manager > 問題:請問現在 yarn 總運算資源有多少? > 答:實體主機也會需要cpu,記憶體,因此也要資源分配,記憶體打八折。CPU 可以多個程式使用同一個 core > 記憶體:64*0.8=51.2 取整數 51 > CPU:12*2=24c ![](https://i.imgur.com/yxrUmeH.png) ![](https://i.imgur.com/xXa1X2N.png) > 問題:現在系統規定一個 container 記憶體範圍定在 1024m~2048m,但是程式設計師他的程式規劃 map 和 reduce ,記憶體大小 384m 和 512m ,這樣這之程式一定不會過,如果是你請問會怎麼做? > 答:直接把 map 和 reduce 的記憶體都改成 1024m。因為只有我們會知道mapred-site.XML這個檔案。 ## bzip2 ![](https://i.imgur.com/fSVFU76.png) * 因為zip不能在切開的狀態下作解壓縮,所以必須把block 合起來才能做unzip 解壓縮。 * 因為Hadoop 是分散式處理,所以要先把block檔get 出linux ,才能作解壓縮動作 ![](https://i.imgur.com/daxwkSS.png) * BZIP2在壓縮時會以每100K為一個單位儲存 * Bzip2演算法於壓縮時,便會先以切割區塊(100K)的形式建立壓縮檔,後續使用hdfs dfs -put上傳 HDSF後,會被切成 blocks 分散儲存,其特性讓map可以直接處裡block的解壓縮 (能以區塊去解壓縮) 並記錄在shuffle,再 merge 成完整檔案交由 reduce 分析運算存回hdfs ### MapReduce 處理 bzip2 檔案 (一) ```! $ hadoop fs -mkdir -p mydataset/sales $ wget http://eforexcel.com/wp/wp-content/uploads/2017/07/1000000%20Sales%20Records.zip $ unzip '1000000 Sales Records.zip' $ dir '1000000 Sales Records.csv' -rw-r--r-- 1 bigred bigred 120M 7月 29 2017 '1000000 Sales Records.csv' $ head -n 3 1000000\ Sales\ Records.csv Region,Country,Item Type,Sales Channel,Order Priority,Order Date,Order ID,Ship Date,Units Sold,Unit Price,Unit Cost,Total Revenue,Total Cost,Total Profit Sub-Saharan Africa,South Africa,Fruits,Offline,M,7/27/2012,443368995,7/28/2012,1593,9.33,6.92,14862.69,11023.56,3839.13 Middle East and North Africa,Morocco,Clothes,Online,M,9/14/2013,667593514,10/19/2013,4611,109.28,35.84,503890.08,165258.24,338631.84 $ cat 1000000\ Sales\ Records.csv | grep Taiwan | wc -l 5483 ``` ### MapReduce 處理 bzip2 檔案 (二) ``` # 把 csv 檔壓縮成 bz2 # -k 壓縮完後原本的檔案還要存在 # -1 壓縮後的檔案每個要 100k $ bzip2 -1 -kz '1000000 Sales Records.csv' -c > sales.bz2 -z --compress force compression -k --keep keep (don't delete) input files -1 .. -9 set block size to 100k .. 900k $ dir sales.bz2 -rw-r--r-- 1 bigred bigred 30M 7月 28 09:14 sales.bz2 # -put 丟到 hdfs # dfs.block.size=16m 對這個檔案每個 block 16m # 這個檔案大小 30m 每個 block 存 16m 因此會存兩個 block $ hadoop fs -D dfs.block.size=16m -put sales.bz2 mydataset/sales/ # 檢查這個檔案是否存兩個 block $ hdfs fsck mydataset/sales/sales.bz2 ...... Total blocks (validated): 2 (avg. block size 15386158 B) # 兩個 block ........ ``` * bzip2 可 spiltable, 所以會用二個 Map Process 處理 bzip2 檔案內容, 因它有 2 個 Block ```! $ yarn jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.3.jar grep mydataset/sales/ tmp/sales/ 'Taiwan' $ hdfs dfs -ls tmp/sales/ Found 2 items -rw-r--r-- 2 bigred bigboss 0 2020-07-08 04:48 /tmp/sales/_SUCCESS -rw-r--r-- 2 bigred bigboss 12 2020-07-08 04:48 /tmp/sales/part-r-00000 $ hdfs dfs -cat tmp/sales/part-r-00000 5483 Taiwan ``` > 問題:一個檔案存到 hdfs ,那硬碟的需求會如何? > 答:一個檔案存到 hdfs ,hdfs 會存三份,因此 1g 的資料存到 hdfs 就變成 3g。 > 問題:承上題,那要如何解決? > 答:透過 bzip2 我先把原本 1t 的檔案做壓縮,變成大約 250g ,在丟到 hdfs ,因此在 hdfs 檔案大小才 750g ,並且最重要的是這個壓縮檔可以被 map 分析處理。 ###### tags: `資料科技`