# 【Hadoop 分散式存儲: 安裝與介紹】
:::info
- 什麼是Hadoop?
- 安裝Hadoop
- HDFS(Distributed File System) & MapReduce
- Mrjob
:::
### 什麼是Hadoop?
Hadoop是一個開源的分散式計算框架,能夠在集群中橫向擴展,通過添加更多的機器節點,處理不斷增長的數據量
通常會有不同的vm,當作不同的節點,Master(主節點),是集群的主要控制中心,負責協調和管理整個集群的運行;slave(從節點),從節點是集群中的工作節點,它們實際執行分散式計算任務
使用Google的MapReduce計算模型,並以分散式文件系統(HDFS)作為其主要存儲系統

<br/>
### 安裝Hadoop
- 方法一
步驟一: 裝 virtual box + Ubuntu Server
網友文章
裝Server版比較省空間!
[VirtualBox 安裝 Ubuntu Server 設定與教學-使用 subiquity 安裝程式](https://www.kjnotes.com/linux/102#google_vignette)
>PS 要多一步,選網路橋接面卡
>
>
安裝好後,能夠登入(輸入安裝時設定的帳號密碼)就成功了


<br/>
>因為介面很難用,下載[PUTTY](https://putty.org/)來連線
>輸入sudo apt get install net-tool,讓它跑一下
>輸入ifconfig
>
>紅色的IP地址貼到PUTTY,綠色的部分可以取名保存起來
>
>改字體大小
>
>登入(輸入安裝時設定的帳號密碼)
>成功進入會長這樣
>
步驟二: 裝Hortonworks Data Platform
網站上找不到免費載點,從國外論壇看到的,直接google貼上,會自動下載
```=
https://archive.cloudera.com/hwx-sandbox/hdp/hdp-2.6.5/HDP_2.6.5_virtualbox_180626.ova
```
步驟三:點開下載檔
會跳到虛擬機,容量要夠不然會匯入失敗

進入成功後,去google網址輸入**http://127.0.0.1:8088**,就能進到Apache Ambari,簡化Apache Hadoop集群的開源集群管理和監控工具
<br/>
- 方法二
步驟一: 跟方法一相同
<br/>
步驟二: 方法一檔案滿大的,我的電腦跑不太動,改用指令裝(參考google+chatgpt)
VM 先再製一個備用


假設我操作的這台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
```
示意圖

```=
sudo vi /etc/hostname
```

確認更改主機名稱
```=
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
```

建立rsa公用密鑰
```=
ssh-keygen -t rsa -P ""
```

使用密鑰登入本機
```=
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
>
>打開後輸入IP地址、ubuntu server 設的使用者帳號密碼
>
>會進到這,左邊本機端的資料就能直接拖曳到右邊Linux了
>
* 或是直接使用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
```

確認服務都正常運行
```=
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(分佈式流媒體平台,用在構建實時數據管道和流應用程序)...


