# 【Hadoop 分散式存儲: 安裝與介紹】 :::info - 什麼是Hadoop? - 安裝Hadoop - HDFS(Distributed File System) & MapReduce - Mrjob ::: ### 什麼是Hadoop? Hadoop是一個開源的分散式計算框架,能夠在集群中橫向擴展,通過添加更多的機器節點,處理不斷增長的數據量 通常會有不同的vm,當作不同的節點,Master(主節點),是集群的主要控制中心,負責協調和管理整個集群的運行;slave(從節點),從節點是集群中的工作節點,它們實際執行分散式計算任務 使用Google的MapReduce計算模型,並以分散式文件系統(HDFS)作為其主要存儲系統 ![hadoop-ecosystem-projects-architecture](https://hackmd.io/_uploads/r1hQoBxDp.png) <br/> ### 安裝Hadoop - 方法一 步驟一: 裝 virtual box + Ubuntu Server 網友文章 裝Server版比較省空間! [VirtualBox 安裝 Ubuntu Server 設定與教學-使用 subiquity 安裝程式](https://www.kjnotes.com/linux/102#google_vignette) >PS 要多一步,選網路橋接面卡 >![螢幕擷取畫面 2023-12-19 194945](https://hackmd.io/_uploads/HJOYQZyva.png) >![螢幕擷取畫面 2023-12-19 195010](https://hackmd.io/_uploads/BJ297ZJDp.png) 安裝好後,能夠登入(輸入安裝時設定的帳號密碼)就成功了 ![螢幕擷取畫面 2023-12-20 122109](https://hackmd.io/_uploads/By4e3Jewa.png) ![螢幕擷取畫面 2023-12-19 143817](https://hackmd.io/_uploads/Byedcn0UT.png) <br/> >因為介面很難用,下載[PUTTY](https://putty.org/)來連線 >輸入sudo apt get install net-tool,讓它跑一下 >輸入ifconfig >![1702987263820](https://hackmd.io/_uploads/Skdp8ZyDp.jpg) >紅色的IP地址貼到PUTTY,綠色的部分可以取名保存起來 >![1702987547877](https://hackmd.io/_uploads/Sy-BPb1Pa.jpg) >改字體大小 >![1702987643275](https://hackmd.io/_uploads/Byu5vWkP6.jpg) >登入(輸入安裝時設定的帳號密碼) >成功進入會長這樣 >![1702987766621](https://hackmd.io/_uploads/SyLM_b1v6.jpg) 步驟二: 裝Hortonworks Data Platform 網站上找不到免費載點,從國外論壇看到的,直接google貼上,會自動下載 ```= https://archive.cloudera.com/hwx-sandbox/hdp/hdp-2.6.5/HDP_2.6.5_virtualbox_180626.ova ``` 步驟三:點開下載檔 會跳到虛擬機,容量要夠不然會匯入失敗 ![螢幕擷取畫面 2023-12-19 155936](https://hackmd.io/_uploads/SJH5TTR8p.png) 進入成功後,去google網址輸入**http://127.0.0.1:8088**,就能進到Apache Ambari,簡化Apache Hadoop集群的開源集群管理和監控工具 <br/> - 方法二 步驟一: 跟方法一相同 <br/> 步驟二: 方法一檔案滿大的,我的電腦跑不太動,改用指令裝(參考google+chatgpt) VM 先再製一個備用 ![螢幕擷取畫面 2023-12-20 121516](https://hackmd.io/_uploads/HyAwq1evp.png) ![螢幕擷取畫面 2023-12-20 121551](https://hackmd.io/_uploads/rJstcylwa.png) 假設我操作的這台ip 192.168.50.40 是master,有另外兩台ip 192.168.50.50、192.168.50.60 要當slave Hadoop是Java編寫的,先安裝Java、OpenJDK(一個開源的Java實現) ```= sudo apt update sudo apt install openjdk-8-jdk ``` 設定 hosts 、hostname ```= sudo vi /etc/hosts ``` 示意圖 ![1703044620084](https://hackmd.io/_uploads/HyXVU1gDT.jpg) ```= sudo vi /etc/hostname ``` ![螢幕擷取畫面 2023-12-20 115928](https://hackmd.io/_uploads/SkrnUklDa.png) 確認更改主機名稱 ```= sudo hostnamectl set-hostname master ``` 建立group,之後比較好管理 ```= sudo addgroup hadoop_group ``` 建立使用者帳戶,加進group,會要你設密碼 ```= sudo adduser --ingroup hadoop_group hadoop_catalina ``` sudo vi /etc/sudoers 使用者帳戶加入sudo權限 (可能會沒有權限存,wq!強制保存並退出) ```= hadoop_catalina ALL=(ALL:ALL) ALL ``` 切換到剛剛設的使用者帳戶 ```= su hadoop_catalina ``` ![螢幕擷取畫面 2023-12-20 130210](https://hackmd.io/_uploads/rkOvHgevT.png) 建立rsa公用密鑰 ```= ssh-keygen -t rsa -P "" ``` ![1703048582582](https://hackmd.io/_uploads/Byw9Bllwp.jpg) 使用密鑰登入本機 ```= cat /home/hadoop_catalina/.ssh/id_rsa.pub >> /home/hadoop_catalina/.ssh/authorized_keys ``` 測試SSH 使用 hadoop_catalina 登入 localhost ```= ssh localhost ``` 將SSH的公鑰複製給slave ```= ssh-copy-id hadoop_catalina@192.168.50.50 ssh-copy-id hadoop_catalina@192.168.50.60 ``` 這時master,要試試能不能"非密碼"登入slave ```= ssh slave ``` 開始安裝~ 訪問[Hadoop官網](https://hadoop.apache.org/)下載Hadoop,解壓縮文件: ```= sudo tar -xzvf hadoop-<version>.tar.gz ``` >可以下載WinSCP把檔案傳進LINUX >![螢幕擷取畫面 2023-12-19 203440](https://hackmd.io/_uploads/SJNXRbkPa.png) >打開後輸入IP地址、ubuntu server 設的使用者帳號密碼 >![1702989459742](https://hackmd.io/_uploads/rkveyz1vp.jpg) >會進到這,左邊本機端的資料就能直接拖曳到右邊Linux了 >![1702989488594](https://hackmd.io/_uploads/SkSJkzywa.jpg) * 或是直接使用wget下載,但版本號要看清楚 ```= wget http://us.mirrors.quenda.co/apache/hadoop/common/hadoop-3.2.0/hadoop-3.3.6.tar.gz ``` 解壓縮 ```= sudo tar -zxvf hadoop-3.3.6.tar.gz ``` 解壓縮的文件夾移動到所需的位置 ```= sudo mv hadoop-<version> /usr/local/hadoop ``` 修改資料夾擁有者權限給 Hadoop Group,讓他可以擁有該資料夾的操作權限 ```= sudo chown -R :hadoop_group /usr/local/hadoop sudo chmod -R g+rwx /usr/local/hadoop ``` 修改 bashrc 文件 ```= sudo vi ~/.bashrc # 下面加入 # Set HADOOP_HOME export HADOOP_HOME=/usr/local/hadoop # Set JAVA_HOME export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 # Set HBase export HBASE_HOME=/usr/local/hbase export HADOOP_INSTALL=$HADOOP_HOME export HADOOP_MAPRED_HOME=$HADOOP_HOME export HADOOP_COMMON_HOME=$HADOOP_HOME export HADOOP_HDFS_HOME=$HADOOP_HOME export YARN_HOME=$HADOOP_HOME export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native" # Add Hadoop bin and sbin directory to PATH export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HBASE_HOME/bin export HADOOP_CLASSPATH=$JAVA_HOME/lib/tools.jar ``` 應用bashrc ```= source ~/.bashrc ``` 進入Hadoop的配置目錄 ```= cd /usr/local/hadoop/etc/hadoop ``` vi hadoop-env.sh文件,設置Java的路徑 ```= # 在每一個節點上都設置Java的路徑 # 下方加入 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 # 或是直接修改,因為前面已經在 bashrc中設定了JAVA_HOME的位置 export JAVA_HOME=${JAVA_HOME} ``` vi core-site.xml文件,添加 ```= <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://master:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/tmp</value> <description>Abase for other temporary directories.</description> </property> </configuration> ``` vi hdfs-site.xml文件 ```= <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration> ### ``` vi yarn-site.xml文件 ```= <configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>master</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration> ### ``` 為了要能認得slave的namenode ```= sudo vi etc/hadoop/workers ``` 裡面localhost改成 ```= master slave ``` 壓縮打包給slave ```= sudo tar -zcf ./hadoop.tar.gz ./hadoop ``` 傳輸到slave ```= scp ./hadoop.tar.gz slave:/home/hadoop_catalina/hadoop/ ``` 在slave執行以下命令,確保 /home/hadoop_catalina/hadoop/ 的擁有者是 hadoop_catalina ```= sudo chown -R hadoop_admin:hadoop_admin /home/hadoop_admin/hadoop/ # 解壓縮 sudo tar -zxf hadoop.tar.gz -C /usr/local/ ``` 啟動Hadoop(會叫你要等十秒) ```= cd /usr/local/hadoop/sbin # 先格式化 name node /usr/local/hadoop/bin/hdfs namenode -format /usr/local/hadoop/sbin/start-all.sh ``` >下次要登入如果失敗,先暫停yarn再重啟 ```= cd /usr/local/hadoop/sbin /usr/local/hadoop/sbin/stop-yarn.sh /usr/local/hadoop/sbin/start-yarn.sh /usr/local/hadoop/sbin/stop-all.sh /usr/local/hadoop/sbin/start-all.sh ``` ![螢幕擷取畫面 2023-12-19 214412](https://hackmd.io/_uploads/rkkIAG1Pp.png) 確認服務都正常運行 ```= jps ``` 允許防火牆 ```= sudo ufw allow 50070 sudo ufw allow 8088 ``` 看log ```= cd /usr/local/hadoop/logs/ ll ``` 看HDFS健康狀態 ```= hdfs dfsadmin -report ``` 看yarn健康狀態 ```= yarn node -list ``` 取得node資訊 ```= hdfs dfsadmin -report ``` 看web ui介面 ```= ResourceManager: http://{master_ip}:9870 ResourceManager Web UI(YARN): http://{master_ip}:8088 NameNode Web UI(HDFS): http://{master_ip}:50070 ``` <br/> >PS start-all.sh 腳本通常用於一次啟動Hadoop集群中的所有服務(包含HDFS和YARN)實際生產環境中,為了更好的控制,通常會分別啟動服務 > >主節點上運行以下命令啟動Hadoop服務 ```= hdfs namenode -format start-dfs.sh start-yarn.sh ``` > >從節點(192.168.50.50和192.168.50.60)上啟動Hadoop服務 ```= start-dfs.sh start-yarn.sh ``` <br/> 步驟三: 查看ui介面 ```= sudo apt install subversion ``` ```= svn checkout http://svn.apache.org/repos/asf/ambari/trunk ambari ``` ### HDFS(Distributed File System) & MapReduce 分散式文件系統 HDFS 是Hadoop的文件存儲系統,設計用於在大量節點上存儲和檢索數據。HDFS具有高容錯性,能夠處理硬件故障,並支持高度可擴展性 MapReduce分為兩個階段:Map階段處理數據並生成中間結果,Reducer主要目的是將 Map 階段輸出的數據按照分區進行整合 為什麼說是安裝與介紹...因為我只有裝過、傳過檔案,和寫過簡單的 mapreduce檔XD (下面範例是用網上範例改的) 假設要做分散式處理 100g的檔案top10000movies.csv,分散式處理並分析 master ip 192.168.50.40 slave1 ip 192.168.50.50 slave2 ip 192.168.50.60 30% 30% 40% top10000movies.csv 上傳到 HDFS ```= hdfs dfs -copyFromLocal /path/to/top10000movies.csv /user/<your_username>/ ``` 假設用 Pandas 和 Hadoop Streaming API處理 ```= # mapper.py import sys import pandas as pd for i, line in enumerate(sys.stdin): movie_data = line.strip().split(',') columns = ["col1", "col2", "col3", ...] movie_dict = dict(zip(columns, movie_data)) if i % 10 < 3: # 30% 的數據分配到 master partition = "master" elif i % 10 < 6: # 30% 的數據分配到 slave1 partition = "slave1" else: # 剩餘 40% 的數據分配到 slave2 partition = "slave2" print(f"{partition}\t{pd.Series(movie_dict).to_csv(index=False, header=False)}", end='') ``` ```= # reducer.py import sys current_partition = None current_movies = [] for line in sys.stdin: partition, movie_data = line.strip().split('\t', 1) # 如果 current_partition 是空的,表示這是第一行,將其設置為當前分區 if current_partition is None: current_partition = partition # 如果分區發生變化,表示已經處理完當前分區的所有影片數據,進入 else 分支進行處理 if partition == current_partition: current_movies.append(movie_data) else: # 進行對 current_movies 的處理,例如排序、篩選等 for movie in current_movies: print(f"{current_partition}\t{movie}") current_partition = partition current_movies = [movie_data] # 處理最後一個 partition 的 movies for movie in current_movies: print(f"{current_partition}\t{movie}") ``` 設置腳本權限 ```= chmod +x mapper.py ``` Hadoop Streaming API 執行 MapReduce 任務 ```= hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar \ -files mapper.py,reducer.py -mapper "python3 mapper.py" -reducer "python3 reducer.py" \ -input /user/<your_username>/top10000movies.csv -output /user/<your_username>/output ``` MapReduce 的輸出結果複製回本地 ```= hdfs dfs -copyToLocal /user/<your_username>/output /path/to/local/output ``` >PS >Hadoop Streaming 的基本概念是,用戶可以使用標準的輸入和輸出來執行Map和Reduce過程,只需要提供兩個可執行的程序(一個用在Map,一個用在Reduce),不一定需要編寫Java代碼 <br/> ### Mrjob mrjob 允許開發人員使用【Python】,來撰寫MapReduce程式 ```= pip install mrjob ``` 建立一個 MRJob 子類,並編寫 mapper 和 reducer 方法 ```= from mrjob.job import MRJob import pandas as pd class MovieAnalysis(MRJob): def mapper(self, _, line): movie_data = line.strip().split(',') columns = ["col1", "col2", "col3", ...] movie_dict = dict(zip(columns, movie_data)) if self.generate_partition() == "master": yield "master", pd.Series(movie_dict).to_csv(index=False, header=False) elif self.generate_partition() == "slave1": yield "slave1", pd.Series(movie_dict).to_csv(index=False, header=False) else: yield "slave2", pd.Series(movie_dict).to_csv(index=False, header=False) def reducer(self, partition, values): # 對 values 的處理,例如排序、篩選等 for movie in values: yield partition, movie def generate_partition(self): # 生成分區的邏輯 if self.increment_counter('Partition', 'total_lines') % 10 < 3: return "master" elif self.increment_counter('Partition', 'total_lines') % 10 < 6: return "slave1" else: return "slave2" if __name__ == '__main__': MovieAnalysis.run() ``` 執行 MapReduce 任務 ```= python your_mrjob_script.py -r hadoop hdfs:///user/<your_username>/top10000movies.csv ``` <br/> ### 更多生態系統 這些我就沒碰過了,只知道大概在能做什麼 Pig Latin(用在數據流程編程)、Hive(用在數據查詢和分析)、HBase(用在分布式NoSQL數據庫)、Spark(用在分散式計算引擎)、Apache Ambari(管理、監控和測試平台)、Apache Kafka(分佈式流媒體平台,用在構建實時數據管道和流應用程序)... ![Hadoop-ecosystem](https://hackmd.io/_uploads/Sy1mHD-vp.png) ![external_data_storage](https://hackmd.io/_uploads/rJzQrw-va.png) ![query_engines](https://hackmd.io/_uploads/SkEmBPWDp.png)