本文主要記錄Mac下如何進行Hadoop僞分佈模式安裝,並經過詞頻統計Demo程序(WordCount)理解MapReduce的原理。html
Hadoop和Spark是兩種不一樣的大數據處理框架,以下圖所示。java
Hadoop 一般包括2個部分:存儲和處理。存儲部分就是Hadoop的分佈式文件系統(HDFS),處理指的是MapReduce(MP)。node
Hadoop 安裝模式分爲3種,分別是單機模式,僞分佈模式和全分佈模式。默認安裝是單機模式。能夠經過配置文件 core-site.xml
,將默認的單機模式更改成僞分佈模式。git
關於Hadoop 3種安裝模式和如何使用虛擬機進行分佈式安裝,能夠參考《Hadoop應用技術詳解》書籍的第2章節——Hadoop安裝。github
Hadoop 的運行方式是由配置文件決定的,所以若是須要從僞分佈式模式切換回非分佈式模式,須要刪除
core-site.xml
中的配置項。算法
下面簡單記錄,如何經過修改配置文件,在 Mac 上搭建僞分佈模式 Hadoop 環境。shell
Hadoop的安裝和配置步驟以下(具體細節參考上述參考連接)數據庫
ssh localhost
進行驗證。hadoop 2.10.0
。將下載的 .tar.gz
壓縮包解壓並放置到 /Library/hadoop-2.10.0
路徑。(1) 打開配置文件apache
vim ~/.bash_profile
複製代碼
(2) 設置環境變量vim
HADOOP_HOME=/Library/hadoop-2.10.0
PATH=$PATH:${HADOOP_HOME}/bin
HADOOP_CONF_DIR=/Library/hadoop-2.10.0/etc/hadoop
HADOOP_COMMON_LIB_NATIVE_DIR=/Library/hadoop-2.10.0/lib/native
export HADOOP_HOME
export PATH
export HADOOP_CONF_DIR
export HADOOP_COMMON_LIB_NATIVE_DIR
複製代碼
(3) 使配置文件生效,並驗證Hadoop版本號
source ~/.bash_profile
hadoop version
複製代碼
須要修改的 Hadoop 配置文件都在目錄 etc/hadoop
下,包括
hadoop-env.sh
core-site.xml
hdfs-site.xml
mapred-site.xml
yarn-site.xml
下面逐步進行修改
(1) 修改 hadoop-env.sh
文件
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home
export HADOOP_HOME=/Library/hadoop-2.10.0
export HADOOP_CONF_DIR=/Library/hadoop-2.10.0/etc/hadoop
複製代碼
(2) 修改 core-site.xml
文件
設置 Hadoop 的臨時目錄和文件系統,localhost:9000
表示本地主機。若是使用遠程主機,要用相應的 IP 地址來代替,填寫遠程主機的域名,則須要到 /etc/hosts
文件中作 DNS 映射。
<configuration>
<!--localhost:9000 表示本地主機-->>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
<!--用來指定hadoop運行時產生文件的存放目錄 本身建立-->
<property>
<name>hadoop.tmp.dir</name>
<value>/Users/lbs/devfiles/hadoop/hadoop-2.10.0/tmp</value>
<description>Directories for software develop and save temporary files.</description>
</property>
</configuration>
複製代碼
(3) 修改 hdfs-site.xml
文件
hdfs-site.xml
指定了 HDFS 的默認參數副本數,由於僅運行在一個節點上(僞分佈模式),因此這裏的副本數爲1。
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<!--不是root用戶也能夠寫文件到hdfs-->
<property>
<name>dfs.permissions</name>
<value>false</value> <!--關閉防火牆-->
</property>
<!--把路徑換成本地的name位置-->
<property>
<name>dfs.namenode.name.dir</name>
<value>/Users/lbs/devfiles/hadoop/hadoop-2.10.0/tmp/dfs/name</value>
</property>
<!--在本地新建一個存放hadoop數據的文件夾,而後將路徑在這裏配置一下-->
<property>
<name>dfs.datanode.data.dir</name>
<value>/Users/lbs/devfiles/hadoop/hadoop-2.10.0/tmp/dfs/data</value>
</property>
</configuration>
複製代碼
(4) 修改 mapred-site.xml
文件
複製 mapred-site.xml.template
模板文件,並修改成 mapred-site.xml
文件,而後將 yarn
設置成數據處理框架,並設置 JobTracker 的主機名與端口。
<configuration>
<property>
<!--指定mapreduce運行在yarn上-->
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
複製代碼
(5) 修改 yarn-site.xml
文件
配置數據的處理框架 yarn
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>localhost:9000</value>
</property>
</configuration>
複製代碼
(1) 第一次啓動Hadoop,須要對 NameNode 進行格式化,後續啓動再也不須要執行此步驟。
hadoop namenode -format
複製代碼
(2) 啓動 HDFS:進入Hadoop 安裝目錄下的 sbin
目錄,並啓動HDFS(須要設置Mac容許遠程登陸,過程當中共須要3次輸入密碼)
Tip: 初次安裝和啓動時,能夠執行
./start-all.sh
,進行必要的初始化安裝
cd /Library/hadoop-2.10.0/sbin
./start-dfs.sh
複製代碼
若出現下述信息,表示啓動成功
lbsMacBook-Pro:sbin lbs$ ./start-dfs.sh
Starting namenodes on [localhost]
Password:
localhost: namenode running as process 12993. Stop it first.
Password:
localhost: datanode running as process 32400. Stop it first.
Starting secondary namenodes [0.0.0.0]
Password:
0.0.0.0: Connection closed by 127.0.0.1 port 22
複製代碼
須要注意的是,在log
中會顯示警告
WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicabled的
複製代碼
上述提醒是關於 Hadoop 本地庫的——Hadoop本地庫是爲了提升效率或者某些不能用Java實現的功能組件庫。能夠參考 Mac OSX 下 Hadoop 使用本地庫提升效率 瞭解詳情。
中止 Hadoop 方法以下
cd /Library/hadoop-2.10.0/sbin
./sbin/stop-dfs.sh
複製代碼
(3) 在終端執行 jps
,若看到以下信息,證實 Hadoop 能夠成功啓動。看到 DataNode
,NameNode
和 SecondaryNameNode
信息,代表啓動的是一個僞分佈模式Hadoop。
lbsMacBook-Pro:sbin lbs$ jps
32400 DataNode
12993 NameNode
30065 BootLanguagServerBootApp
13266 SecondaryNameNode
30039 org.eclipse.equinox.launcher_1.5.700.v20200207-2156.jar
35019 ResourceManager
35117 NodeManager
32926 RunJar
35199 Jps
複製代碼
也能夠訪問 http://localhost:50070/dfshealth.html#tab-overview
來查看 Hadoop的啓動狀況。看到 Live Node
參數,證實僞分佈模式 Hadoop 啓動成功。
(4) 啓動 yarn:進入Hadoop 安裝目錄下的 sbin
目錄,並啓動 yarn
cd /Library/hadoop-2.10.0/sbin
./start-yarn.sh
複製代碼
至此,Hadoop的安裝,配置和啓動就完成啦!接下來能夠經過一些 shell 命令來操做 Hadoop 下的文件了,例如
hadoop fs -ls /        查看根目錄下的文件及文件夾
hadoop fs -mkdir /test 在根目錄下建立一個文件夾 testdata
hadoop fs -rm /.../... 移除某個文件
hadoop fs -rmr /... 移除某個空的文件夾
複製代碼
在啓動 HDFS時,若看到以下警告
./start-dfs.sh
複製代碼
lbsMacBook-Pro:~ lbs$ cd /Library/hadoop-2.10.0/sbin
lbsMacBook-Pro:sbin lbs$ ./start-dfs.sh
20/03/23 08:46:43 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Starting namenodes on [localhost]
Password:
localhost: namenode running as process 93155. Stop it first.
Password:
localhost: datanode running as process 93262. Stop it first.
Starting secondary namenodes [0.0.0.0]
Password:
0.0.0.0: secondarynamenode running as process 93404. Stop it first.
複製代碼
上述提醒是關於 Hadoop 本地庫的——Hadoop本地庫是爲了提升效率或者某些不能用Java實現的功能組件庫。能夠參考 Mac OSX 下 Hadoop 使用本地庫提升效率 瞭解詳情。
pom.xml
中添加以下依賴<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.lbs0912</groupId>
<artifactId>wordcount</artifactId>
<version>1.0-SNAPSHOT</version>
<!--添加 apache 鏡像源-->
<repositories>
<repository>
<id>apache</id>
<url>http://maven.apache.org</url>
</repository>
</repositories>
<!--添加以下依賴-->
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>
</project>
複製代碼
WordMapper
類package wordcount;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class WordMapper extends Mapper<Object, Text, Text, IntWritable> {
IntWritable one = new IntWritable(1);
Text word = new Text();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
複製代碼
WordReducer
類package wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class WordReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException,InterruptedException {
int sum = 0;
for(IntWritable val:values) {
sum += val.get();
}
result.set(sum);
context.write(key,result);
}
}
複製代碼
WordMain
驅動類package wordcount;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
public class WordMain {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
/**
* 這裏必須有輸入/輸出
*/
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}
Job job = new Job(conf, "wordcount");
job.setJarByClass(WordMain.class); //主類
job.setMapperClass(WordMapper.class); //Mapper
job.setCombinerClass(WordReducer.class); //做業合成類
job.setReducerClass(WordReducer.class); //Reducer
job.setOutputKeyClass(Text.class); //設置做業輸出數據的關鍵類
job.setOutputValueClass(IntWritable.class); //設置做業輸出值類
FileInputFormat.addInputPath(job, new Path(otherArgs[0])); //文件輸入
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); //文件輸出
System.exit(job.waitForCompletion(true) ? 0 : 1); //等待完成退出
}
}
複製代碼
選擇 Run -> Edit Configurations
, 在程序參數欄目中輸入 input/ output
,以下圖所示
在 input
目錄中添加統計單詞個數的測試的文件 wordcount1.txt
Hello,i love coding
are you ok?
Hello, i love hadoop
are you ok?
複製代碼
再次運行程序,會看到以下的 output
目錄結構
- input
- output
| - ._SUCCESS.crc
| - .part-r-00000.crc
| - ._SUCCESS
| - part-r-00000
複製代碼
打開 part-r-00000
文件,便可看到單詞出現次數的統計結果
Hello, 1
Hello,i 1
are 2
coding 1
hadoop 1
i 1
love 2
ok? 2
you 2
複製代碼
須要注意的是,因爲Hadoop的設定,下次運行程序前,須要先刪除output文件目錄。
File -> Project Structure
選項中,爲工程添加 Artifacts
,選擇 WordMain
類Build -> Build Artifacts...
,生成 .jar
文件hadoop jar WordCount.jar input/ out/
複製代碼
HDFS(Hadoop Distributed File System
)是一個用在普通硬件設備上的分佈式文件系統。 HDFS 具備高容錯性(fault-tolerant
)和高吞吐量(high throughput
),適合有超大數據集的應用程序,能夠實現經過流的形式訪問文件系統中的數據。
運行在HDFS之上的應用程序必須流式地訪問它們的數據集,它不是典型的運行在常規的文件系統之上的常規程序。HDFS的設計適合批量處理,而不是用戶交互式的,重點是數據吞吐量,而不是數據訪問的反應時間。
HDFS以塊序列的形式存儲每個文件,文件中除了最後一個塊的其餘塊都是相同的大小。
HDFS 爲Hadoop 這個分佈式計算框架一共高性能,高可靠,高可擴展的存儲服務。HDFS是一個典型的主從架構,一個HDFS集羣是由一個主節點(Namenode
)和必定數目的從節點(Datanodes
)組成。
namespace
)以及客戶端對文件的訪問。同時肯定塊和數據節點的映射。
metadata
信息,包括文件 owership
和 permissions
,文件包含有哪些塊,Block
保存在哪一個 DataNode
等metadata
信息在啓動後會加載到內存中Rack
):一個 Block 的三個副本一般會保存到兩個或者兩個以上的機架中,進行防災容錯Block
)是 HDFS 文件系統基本的存儲單位,Hadoop 1.X 默認大小是 64MB,Hadoop 2.X 默認大小是 128MB。HDFS上的文件系統被劃分爲塊大小的多個分塊(Chunk
)做爲獨立的存儲單元。和其餘文件系統不一樣的是,HDFS上小於一個塊大小的文件不會佔據整個塊的空間。使用塊抽象而非整個文件做爲存儲單元,大大簡化了存儲子系統的設計。SecondaryNameNode
)負責鏡像備份,日誌和鏡像的按期合併。使用
hadoop fsk / -files -blocks
能夠顯示塊的信息。
Block 數據塊大小設置的考慮因素包括
Block 是 HDFS 文件系統的最小組成單元,它經過一個 Long
整數被惟一標識。每一個 Block 會有多個副本,默認有3個副本。爲了數據的安全和高效,Hadoop 默認對3個副本的存放策略以下圖所示
這樣的策略能夠保證對該 Block 所屬文件的訪問可以優先在本 Rack 下找到。若是整個 Rack 發生了異常,也能夠在另外的 Rack 找到該 Block 的副本。這樣足夠高效,而且同時作到了數據的容錯。
RPC(Remote Procedure Call
)即遠程過程調用機制會面臨2個問題
RPC 架構以下圖所示。Hadoop 本身實現了簡單的 RPC 組件,依賴於 Hadoop Writable
類型的支持。
Hadoop Writable
接口要求每一個實現類多要確保將本類的對象正確序列化(writeObject
)和反序列化(readObject
)。所以,Hadoop RPC 使用 Java 動態代理和反射實現對象調用方式,客戶端到服務器數據的序列化和反序列化由 Hadoop框架或用戶本身來實現,也就是數據組裝定製的。
Hadoop RPC = 動態代理 + 定製的二進制流
HBase 的特色以下
有句話說得好,「大數據勝於算法」,意思是說對於某些應用(例如根據以往的偏好來推薦電影和音樂),不論算法有多牛,基於小數據的推薦效果每每都不如基於大量可用數據的通常算法的推薦效果。 —— 《Hadoop 權威指南》