Spark的分布式架構
如我們所知,spark之所以強大,除了強大的數據處理功能,另一個優勢就在於良好的分布式架構。舉一個例子在Spark實戰--尋找5億次訪問中,訪問次數最多的人中,我用四個spark節點去嘗試尋找5億次訪問中,次數最頻繁的ID。這一個過程耗時竟然超過40分鍾,對一個程序來說,40分鍾出結果這簡直就是難以忍耐。但是在大數據處理中,這又是理所當然的。當然實際中不可能允許自己的程序在簡單的僅處理五億次訪問中耗費如此之大的時間,因此考慮了分布式架構。(PS:當然處理5億次請求的示例中,我們實際采用的其實是四個節點,三台機子的偽分布式架構)
分布式架構的優勢
還是以上面Spark實戰--尋找5億次訪問中,訪問次數最多的人作為例子,如果我們四個節點(實際上三台機子)處理了四十分鍾,如果我們用一千個相同配置的節點上,理論上這個時間會縮短到2.4分鍾。如果我們再增加節點的性能,比如內存、CPU性能、核數等這個理論值會縮短到更小的值。但是,實際上這個理論值永遠達不到,這一點顯而易見,因為spark調度、分配、網絡等時間消耗,因此這個值會比2.4分鍾大一些。但是相較於47分鍾,這個值已經非常令人滿意了。為了達到spark的性能,我們常常會對其進行調優,這是后話了。
從零開始搭建我們的Spark平台
1、准備centeros環境
為了搭建一個真正的的集群環境,並且要做到高可用的架構,我們至少准備三個虛擬機來作為集群節點。因此我購買了三台阿里雲的服務器,來作為我們的集群節點。
Hostname | IP | 內存 | CPU |
---|---|---|---|
master | 172.19.101.111 | 4G | 1核 |
slave1 | 172.19.77.91 | 4G | 1核 |
slave2 | 172.19.131.1 | 4G | 1核 |
注意到,master是主節點,而slave顧名思義就是奴隸,自然就是為主節點工作的節點。實際上,在我們這個集群中,master和slave並沒有那么明確的區分,因為事實上他們都在“努力地工作”。當然在搭建集群的時候,我們依然要明確這個概念。
2、下載jdk
- 1、下載jdk1.8 tar.gz包
wget https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.tar.gz
- 2、解壓
tar -zxvf jdk-8u201-linux-x64.tar.gz
解壓之后得到

- 3、配置環境變量
修改profile
vi /etc/profile
添加如下
export JAVA_HOME=/usr/local/java1.8/jdk1.8.0_201 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH

source使其生效
source /etc/profile
查看是否生效
java -version

看到如圖內容表示已經成功。
以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
3、安裝zookeeper
- 下載zookeeper包
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

- 解壓
tar -zxvf zookeeper-3.4.13.tar.gz

- 進入zookeeper配置目錄
cd zookeeper-3.4.13/conf
- 拷貝配置文件模板
cp zoo_sample.cfg zoo.cfg

- 拷貝后修改zoo.cfg內容
dataDir=/home/hadoop/data/zkdata
dataLogDir=/home/hadoop/log/zklog server.1=master:2888:3888 server.2=slave1:2888:3888 server.3=slave2:2888:3888

- 配置環境變量
export ZOOKEEPER_HOME=/usr/local/zookeeper/zookeeper-3.4.13 export PATH=$PATH:$ZOOKEEPER_HOME/bin

- 使環境變量生效
source /etc/profile
- 注意到前面配置文件中這句話,配置了數據目錄
dataDir=/home/hadoop/data/zkdata
- 我們手動創建該目錄,並且進入到其中
cd /home/hadoop/data/zkdata/ echo 3 > myid

- 這里需要特別注意這個
echo 1 > myid
- 這是對於這個配置,因此在master中我們echo 1,而對於slave1則是 echo 2,對於slave2則是 echo 3
server.1=master:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888

- 配置完啟動測試
zkServer.sh start

- 啟動后查看是否啟動成功
zkServer.sh status

以上操作三台虛擬機都要進行!只有echo 不一樣 以上操作三台虛擬機都要進行!只有echo 不一樣 以上操作三台虛擬機都要進行!只有echo 不一樣
- 在master中啟動后查看狀態

- 在salve1中啟動后查看狀態

這里面的Mode是不一樣的,這是zookeeper的選舉機制,至於該機制如何運行,這里按下不表。后續會有專門說明。 至此,zookeeper集群已經搭建完成
4、安裝hadoop
- 1、通過wget下載hadoop-2.7.7.tar.gz
wget http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.7.7/hadoop-2.7.7.tar.gz
- 2、下載后解壓
解壓出一個hadoop-2.7.7目錄
tar -zxvf hadoop-2.7.7

- 3、配置hadoop環境變量
修改profile
vi /etc/profile
- 增加hadoop環境變量
export HADOOP_HOME=/usr/local/hadoop/hadoop-2.7.7 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:

- 使環境變量生效
source /etc/profile
- 配置完之后,查看是否生效
hadoop version

-
進入hadoop-2.7.7/etc/hadoop中
-
編輯core-site.xml
vi core-site.xml
- 增加configuration
<configuration>
<!-- 指定hdfs的nameservice為myha01 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://myha01/</value>
</property>
<!-- 指定hadoop臨時目錄 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/data/hadoopdata/</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<!-- hadoop鏈接zookeeper的超時時長設置 -->
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>1000</value>
<description>ms</description>
</property>
</configuration>

- 拷貝mapred-site.xml.template
cp mapred-site.xml.template mapred-site.xml

- 編輯mapred-site.xml
vi mapred-site.xml
- 增加如下內容
<configuration>
<!-- 指定mr框架為yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 指定mapreduce jobhistory地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<!-- 任務歷史服務器的web地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
</configuration>
- 編輯hdfs-site.xml
vi hdfs-site.xml
- 增加如下內容
<configuration>
<!-- 指定副本數 -->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<!-- 配置namenode和datanode的工作目錄-數據存儲目錄 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/data/hadoopdata/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/data/hadoopdata/dfs/data</value>
</property>
<!-- 啟用webhdfs -->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value> </property> <!--指定hdfs的nameservice為myha01,需要和core-site.xml中的保持一致 dfs.ha.namenodes.[nameservice id]為在nameservice中的每一個NameNode設置唯一標示符。 配置一個逗號分隔的NameNode ID列表。這將是被DataNode識別為所有的NameNode。 例如,如果使用"myha01"作為nameservice ID,並且使用"nn1"和"nn2"作為NameNodes標示符 --> <property> <name>dfs.nameservices</name> <value>myha01</value> </property> <!-- myha01下面有兩個NameNode,分別是nn1,nn2 --> <property> <name>dfs.ha.namenodes.myha01</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.myha01.nn1</name> <value>master:9000</value> </property>

- 編輯yarn-site.xml
vi yarn-site.xml
- 增加如下內容
<configuration>
<!-- 開啟RM高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value> </property> <!-- 指定RM的cluster id --> <property> <name>yarn.resourcemanager.cluster-id</name> <value>yrc</value> </property> <!-- 指定RM的名字 --> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <!-- 分別指定RM的地址 --> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>slave1</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>slave2</value> </property> <!-- 指定zk集群地址 --> <property> <name>yarn.resourcemanager.zk-address</name> <value>master:2181,slave1:2181,slave2:2181</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.log-aggregation-enable</name> <value>true</value> </property> <property> <name>yarn.log-aggregation.retain-seconds</name> <value>86400</value> </property> <!-- 啟用自動恢復 --> <property> <name>yarn.resourcemanager.recovery.enabled</name> <value>true</value> </property> <!-- 制定resourcemanager的狀態信息存儲在zookeeper集群上 --> <property> <name>yarn.resourcemanager.store.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value> </property> </configuration>

- 最后編輯salves
master
slave1
slave2

以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
-
接着就可以啟動hadoop
-
首先在三個節點上啟動journalnode,切記三個節點都要操作
hadoop-daemon.sh start journalnode
- 操作完成后用jps命令查看,可以看到

-
其中QuorumPeerMain是zookeeper,JournalNode則是我啟動的內容
-
接着對主節點的namenode進行格式化
hadoop namenode -format

-
注意標紅色方框的地方
-
完成格式化后查看/home/hadoop/data/hadoopdata目錄下的內容

- 目錄中的內容拷貝到slave1上,slave1是我們的備用節點,我們需要他來支撐高可用模式,當master宕機的時候,slave1馬上能夠頂替其繼續工作。
cd..
scp -r hadoopdata/ root@slave1:hadoopdata/

- 這樣就確保了主備節點都保持一樣的格式化內容
接着就可以啟動hadoop
- 首先在master節點啟動HDFS
start-dfs.sh

- 接着啟動start-yarn.sh ,注意start-yarn.sh需要在slave2中啟動
start-yarn.sh

- 分別用jps查看三個主機
master

slave1

slave2

- 這里注意到master和slave1都有namenode,實際上只有一個是active狀態的,另一個則是standby狀態。如何證實呢,我們 在瀏覽器中輸入master:50700,可以訪問
- 在瀏覽器中輸入slave1:50700,可以訪問
- 另一種方式,是查看我們配置的兩個節點
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2

5、spark安裝
- 下載spark
wget http://mirrors.shu.edu.cn/apache/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz
- 解壓
tar -zxvf spark-2.4.0-bin-hadoop2.7.tgz

- 進入spark的配置目錄
cd spark-2.4.0-bin-hadoop2.7/conf
- 拷貝配置文件spark-env.sh.template
cp spark-env.sh.template spark-env.sh

編輯spark-env.sh
vi spark-env.sh
- 增加內容
export JAVA_HOME=/usr/local/java1.8/jdk1.8.0_201 export HADOOP_HOME=/usr/local/hadoop/hadoop-2.7.7 export HADOOP_CONF_DIR=/usr/local/hadoop/hadoop-2.7.7/etc/hadoop export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=master:2181,slave1:2181,slave2:2181 -Dspark.deploy.zookeeper.dir=/spark" export SPARK_WORKER_MEMORY=300m export SPARK_WORKER_CORES=1

其中java的環境變量、hadoop環境變量請從系統環境變量中拷貝,后面SPARK_WORKER_MEMORY是spark運行的內存,SPARK_WORKER_CORES是spark使用的CPU核數
以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
以上操作三台虛擬機一模一樣!
- 配置系統環境變量
vi /etc/profile
- 增加內容
export SPARK_HOME=/usr/local/spark/spark-2.4.0-bin-hadoop2.7 export PATH=$PATH:$SPARK_HOME/bin
- 拷貝slaves.template 文件
cp slaves.template slaves
- 使環境變量生效
source /etc/profile
- 編輯slaves
vi slaves
- 增加內容
master
slave1
slave2
-
最后我們啟動spark,注意即便配置了spark的環境變量,由於start-all.sh和hadoop的start-all.sh沖突,因此我們必須進入到spark的啟動目錄下,才能執行啟動所有的操作。
-
進入啟動目錄
cd spark-2.4.0-bin-hadoop2.7/sbin
- 執行啟動
./start-all.sh
-
執行完成后,用jps查看三個節點下的狀態
-
master:

- slave1:

- slave2:

注意到三個節點都有了spark的worker進程,只有master當中有Master進程。
訪問master:8080
至此我們就擁有了正式的spark環境。
6、嘗試使用
由於我們已經配置了環境變量,故可以輸入spark-shell直接開始。
spark-shell

這里我們就進入了spark-shell.
然后進行編碼
val lise = List(1,2,3,4,5)
val data = sc.parallelize(lise)
data.foreach(println)

或者我們進入spark-python
pyspark

查看sparkContext
