一、大数据(Big Data)
体量很大的数据,起步存储当量为TB级或者日均数据增长GB级。
在海量数据下,可以进行分析,挖掘,进而发现数据内在的规律,从而为企业或者国家创造价值。
(1) Volume:体量大
(2)Variety:样式多 数据种类多
1.1 结构化数据
1.2.半结构化数据:json、xml
1.3.非结构化数据:图片、音频、视频
(3) Velocity:速度快
(4) Value:低价值密度的数据,挖掘出高价值。
- 自己公司系统运行产生的 日志 (Nginx,Log4j[埋点日志],数据库中的数据)
- 爬虫
- 行业大数据 电信 医疗 政府 金融
- 大数据交易 (贵州) 脱敏
分布式:服务间出现跨机器、跨进程通信同一称为分布式
2003-2004年,Google公布了部分GFS和MapReduce思想的细节,受此启发的Doug Cutting等人用2年的业余时间实现了DFS和MapReduce机制,使Nutch性能飙升。然后Yahoo招安Doug Gutting及其项目。
2005年:Hadoop作为Lucene的子项目Nutch的一部分正式引入Apache基金会。
2006年2月:yahoo加入Nutch工程尝试将Nutch存储和计算分离出来,成为一套完整独立的软件并起名为Hadoop 。
人称Hadoop之父的Doug Cutting,Apache软件基金会主席,是Lucene、Nutch 、Hadoop等项目的发起人。最开始Hadoop只是Apache Lucene的子项目Nutch的一部分。Lucene 是全球第一个开源的全文检索引擎工具包, Nutch基于Lucene,并具有网页抓取和解析的功能,可以实现一个搜索引擎的开发,但是如果投入使用的话就必须在极短时间内做出反应,并且能够实现短时间内对亿级数量的网页进行分析处理,这就需要考虑分布式任务处理、故障恢复、负载均衡这些问题。后来Doug Cutting 借鉴谷歌的Google File System和MapReduce:Simplified Data Processing On Large Clusters两篇论文,移植了其中的技术,并将其命名为:Hadoop。
HDFS:Hadoop 分布式文件存储系统,解决海量数据的存储问题(非常重要)
Map Reduce:Hadoop项目分布式计算框架(老),已经成为大数据计算的标杆。是早期分布式计算解决方案。期间该方案在2010年又被Yahoo团队做了一次升级,主要解决的是MapReduce在大规模计算集群的扩展性问题,但是并没有本质改变MapReduce计算本质。因为MapReduce计算的是通过对数据做磁盘迭代计算。导致计算速度不算太快。2013年下半年出现了Spark是一款基于内存的分布式计算框架,用于替代Hadoop的MapReduce,被人们称为第二代大数据计算引擎。
Doug Cutting是Lucene(全文搜索技术 Solr ES)、Nutch作者,后续设计开发了Hadoop体系。
Hadoop1.x<---------------------------------------------Google
HDFS(Hadoop Distributed File System) <------GFS
MapReduce<-------------------------------------------MapReduce
HBase <-------------------------------------------------BigTable
apache组织正式开源Hadoop,并把Hadoop作为了顶级项目。
- Hadoop Core (HDFS,MR-MapReduce)
- Hadoop生态工具 (Hive,HBase)
- Hadoop辅助工具 (Flume,Sqoop,Oozie,Hue)
- HDFS 文件系统 (IO) 存数据 取数据
- MapReduce 编程,数据的计算 原有的 Java开发 区别
- Hive 学SQL (HQL Hive Query Lanuage) 类似SQL 95%和SQL语法一致
- Hbase (NoSQL) 类比 Redis 存 取数据
全称Hadoop Distributed File System,是Hadoop一个基于分布式存储通用的文件系统,该系统特点容易部署、对系统硬件要求低,搭建成本可控。可以使得数据存储大小和集群过程呈现一种线性关系 (目前最大已知规模2000台左右规模,实际在生产环境下集群规模一般在10~100台左右)。HDFS文件系统的架构图:
NameNode:使用内存存储集群中的元数据(文件名、权限、位置、大小、创建时间、副本信息、块信息、实际存储数据的datanode信息)
DataNode:HDFS中专门用于存储数据的服务器,负责响应客户端对数据块的读写请求,向NameNode汇报自身状态信息,同时负责对块数据的冗余保存以及存储块数据加密后的校验和。
Block:是HDFS切分文件的尺度,默认是128MB,一个文件最多只有 一个不足128MB块
副本因子:HDFS为了防止DataNode宕机导致块的丢失,允许一个块又多个备份,默认备份是3
案例 | NameNode | DataNode |
---|---|---|
1文件128MB | 1条数据块映射元数据 | 128MB磁盘存储*(副本因子) |
1000文件总计128MB | 1000*1条数据块映射元数据 | 128MB磁盘存储*(副本因子) |
因为Namenode使用单机的内存存储,因此由于小文件会占用更多的内存空间,导致了Namenode内存浪费。
安装虚拟器并且安装CentOS-6.5 64位 (参考[CentOS 64安装.wmv](./CentOS 64安装.wmv))
安装jdk-8u171-linux-x64.rpm配置JAVA_HOME环境变量(~/.bashrc)
[root@CentOS ~]# rpm -ivh jdk-8u171-linux-x64.rpm
[root@CentOS ~]# ls -l /usr/java/
total 4
lrwxrwxrwx. 1 root root 16 Mar 26 00:56 default -> /usr/java/latest
drwxr-xr-x. 9 root root 4096 Mar 26 00:56 jdk1.8.0_171-amd64
lrwxrwxrwx. 1 root root 28 Mar 26 00:56 latest -> /usr/java/jdk1.8.0_171-amd64
[root@CentOS ~]# vi .bashrc
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.
export JAVA_HOME
export PATH
export CLASSPATH
[root@CentOS ~]# source ~/.bashrc # 加载环境变量
[root@CentOS ~]# vi /etc/hosts # 一定是自己的IP
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.40.128 CentOS
[root@CentOS ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
4b:29:93:1c:7f:06:93:67:fc:c5:ed:27:9b:83:26:c0 root@CentOS
The key's randomart image is:
+--[ RSA 2048]----+
| |
| o . . |
| . + + o .|
| . = * . . . |
| = E o . . o|
| + = . +.|
| . . o + |
| o . |
| |
+-----------------+
[root@CentOS ~]# ssh-copy-id CentOS
The authenticity of host 'centos (192.168.40.128)' can't be established.
RSA key fingerprint is 3f:86:41:46:f2:05:33:31:5d:b6:11:45:9c:64:12:8e.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'centos,192.168.40.128' (RSA) to the list of known hosts.
root@centos's password:
Now try logging into the machine, with "ssh 'CentOS'", and check in:
.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.
[root@CentOS ~]# ssh root@CentOS
Last login: Tue Mar 26 01:03:52 2019 from 192.168.40.1
[root@CentOS ~]# exit
logout
Connection to CentOS closed.
# 临时关闭服务
[root@CentOS ~]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter [ OK ]
iptables: Flushing firewall rules: [ OK ]
iptables: Unloading modules: [ OK ]
[root@CentOS ~]# service iptables status
iptables: Firewall is not running.
# 关闭开机自动启动
[root@CentOS ~]# chkconfig iptables off
[root@CentOS ~]# chkconfig --list | grep iptables
iptables 0:off 1:off 2:off 3:off 4:off 5:off 6:off
[root@CentOS ~]# tar -zxf hadoop-2.6.0_x64.tar.gz -C /usr/
[root@CentOS ~]# ls /usr/hadoop-2.6.0/
bin etc include lib libexec LICENSE.txt NOTICE.txt README.txt sbin share
[root@CentOS ~]# vi ~/.bashrc
HADOOP_HOME=/usr/hadoop-2.6.0
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
CLASSPATH=.
export JAVA_HOME
export PATH
export CLASSPATH
export HADOOP_HOME
[root@CentOS ~]# source ~/.bashrc
[root@CentOS ~]# hadoop version
Hadoop 2.6.0
Subversion Unknown -r Unknown
Compiled by root on 2016-08-01T20:48Z
Compiled with protoc 2.5.0
From source with checksum 18e43357c8f927c0695f1e9522859d6a
This command was run using /usr/hadoop-2.6.0/share/hadoop/common/hadoop-common-2.6.0.jar
core-site.xml(配置的是NameNode访问入口,以及服务存储的根目录)
[root@CentOS ~]# vi /usr/hadoop-2.6.0/etc/hadoop/core-site.xml
<!--nn访问入口-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://CentOS:9000</value>
</property>
<!--hdfs工作基础目录-->
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/hadoop-2.6.0/hadoop-${user.name}</value>
</property>
[root@CentOS ~]# vi /usr/hadoop-2.6.0/etc/hadoop/hdfs-site.xml
<!--block副本因子-->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<!--配置Sencondary namenode所在物理主机-->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>CentOS:50090</value>
</property>
<!--关闭HDFS权限管理-->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
[root@CentOS ~]# vi /usr/hadoop-2.6.0/etc/hadoop/slaves
CentOS
如果是第一次初始化启动HDFS服务,需要创建一个空的fsimage文件,以便Namenode在启动的时候加载
[root@CentOS ~]# hdfs namenode -format # 创建初始化所需的fsimage文件
...
19/03/26 01:31:09 INFO namenode.NNConf: Maximum size of an xattr: 16384
19/03/26 01:31:09 INFO namenode.FSImage: Allocated new BlockPoolId: BP-1143348175-192.168.40.128-1553535069443
19/03/26 01:31:09 INFO common.Storage: Storage directory `/usr/hadoop-2.6.0/hadoop-root/dfs/name has been successfully formatted.`
19/03/26 01:31:09 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0
[root@CentOS ~]# start-dfs.sh
Starting namenodes on [CentOS]
CentOS: starting namenode, logging to /usr/hadoop-2.6.0/logs/hadoop-root-namenode-CentOS.out
CentOS: starting datanode, logging to /usr/hadoop-2.6.0/logs/hadoop-root-datanode-CentOS.out
Starting secondary namenodes [CentOS]
CentOS: starting secondarynamenode, logging to /usr/hadoop-2.6.0/logs/hadoop-root-secondarynamenode-CentOS.out
[root@CentOS ~]# jps
2097 SecondaryNameNode
2280 Jps
1993 DataNode
1918 NameNode
#或者访问:http://[IP]:50070/
用户可以通过配置core-site.xml,开启NameNode的垃圾回收。NameNode会根据fs.trash.interval配置配置垃圾回收的频率,默认单位是分钟。表示1分钟内,如果用户不处理删除文件,系统会自动删除回收战的内容。该种机制就是为了防止用户的误操作。
<property>
<name>fs.trash.intervalname>
<value>1value>
property>
HDFS Shell(脚本)
[root@CentOS ~]# hdfs dfs -help
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-cp [-f] [-p | -p[topax]] <src> ... <dst>]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] <localsrc> ... <dst>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-tail [-f] <file>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
①解压hadoop的安装包
②将winutil.exe和hadoop.dll文件拷贝到hadoop安装目录下的bin目录
③在Windows上配置CentOS的主机名和IP的映射关系
192.168.40.128 CentOS
④配置HADOOP_HOME环境变量
⑤重启IDEA开发工具,否则IDAE无法识别HADOOP_HOME,因为windows执行代码程序需要通过HADOOP_HOME定位winutil.exe和hadoop.dll文件。
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-commonartifactId>
<version>2.6.0version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-hdfsartifactId>
<version>2.6.0version>
dependency>
1. Configuration 配置类,进行core-site.xml hdfs-site.xml 配置信息
的读取,操作
2. FileSystem 代表的就是 HDFS分布式文件系统
3. IOUtils IO操作的工具类
public class TestHDFS {
//从HDFS中读取文件在控制台输出
@Test
public void test1() throws Exception{
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://CentOS:8020");
FileSystem fileSystem = FileSystem.get(conf);
FSDataInputStream fsDataInputStream = fileSystem.open(new
Path("/liuh/xiaohei/data"));
IOUtils.copyBytes(fsDataInputStream, System.out, 1024, true);
}
//添加获取FileSystem对象的工具方法,在以下测试中使用
private FileSystem getFileSystem() throws Exception{
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://hadoop2.baizhiedu.com:8020");
FileSystem fileSystem = FileSystem.get(conf);
return fileSystem;
}
//从HDFS中读取文件在控制台输出
@Test
public void test2() throws Exception {
FileSystem fileSystem = getFileSystem();
FSDataInputStream fsDataInputStream = fileSystem.open(new
Path("/liuh/xiaohei/data"));
IOUtils.copyBytes(fsDataInputStream,System.out,1024,true);
}
//加载本地配置文件core-site.xml替代伪分布式中配置。从HDFS中读取文件在控制台输出
@Test
public void test3()throws Exception {
Configuration conf = new Configuration();
conf.addResource(new
Path("C:\\Users\\Administrator\\IdeaProjects\\hadoop_code\\hadoop-hdfsbaizhiedu\\src\\main\\resources\\core-site.xml"));
FileSystem fileSystem = FileSystem.get(conf);
FSDataInputStream fsDataInputStream = fileSystem.open(new
Path("/liuh/xiaohei/data"));
IOUtils.copyBytes(fsDataInputStream, System.out, 1024, true);
}
//从HDFS中读取文件,输出为文件
@Test
public void test4()throws Exception{
FileSystem fileSystem = getFileSystem();
FSDataInputStream fsDataInputStream = fileSystem.open(new
Path("/liuh/xiaohei/data"));
FileOutputStream fileOutputStream = new
FileOutputStream("f://laolei.txt");
IOUtils.copyBytes(fsDataInputStream,fileOutputStream,1024,true);
}
//从本地文件读取内容,写出到HDFS文件中
@Test
public void test5()throws Exception{
FileInputStream fileInputStream = new
FileInputStream("f://xiaojr.txt");
FileSystem fileSystem = getFileSystem();
FSDataOutputStream fsDataOutputStream = fileSystem.create(new
Path("/liuh/xiaohei/data1"));
IOUtils.copyBytes(fileInputStream,fsDataOutputStream,1024,true);
}
//创建删除HDFS目录
@Test
public void test6()throws Exception{
FileSystem fileSystem = getFileSystem();
boolean isOk = fileSystem.mkdirs(new Path("/xiaojr"));
System.out.println("创建目录 "+isOk);
//fileSystem.delete(new Path(""),true);
}
}
是对HDFS的一种保护机制,1)正常情况下当系统在加载fsimage的初期会自动进入安全模式,在该模式下系统不接受外界的任何请求,当加载完数据检查系统完毕,系统会自动离开安全模式。2)如果当DataNode/NameNode使用空间不足时,系统会自动进入安全模式。3).当系统维护时,管理员也可手动的将NameNode切换成安全模式,维护结束再离开。
[root@CentOS ~]# hdfs dfsadmin -safemode get
Safe mode is OFF
[root@CentOS ~]# hdfs dfsadmin -safemode enter
Safe mode is ON
[root@CentOS ~]# hdfs dfs -put /root/install.log /
put: Cannot create file/install.log._COPYING_. Name node is in safe mode.
[root@CentOS ~]# hdfs dfsadmin -safemode leave
Safe mode is OFF
[root@CentOS ~]# hdfs dfs -put /root/install.log /
1. *-default.xml share jar
core-default.xml HDFS整体设置 设置NameNode入口,namenode持久化,存储位置
hdfs-default.xml 设置与HDFS相关信息 副本数量 块大小 hdfs访问权限
yarn-default.xml 与yarn相关
mapred-default.xml 与mapred相关
2. *-site.xml etc/hadoop
# 如果site.xml对default对应的key进行了覆盖,那么就按照site的设置,进行处理,如果没有覆盖,则按照
default处理
core-site.xml HDFS整体设置 设置NameNode入口,namenode持久化,存储位置
hdfs-site.xml 设置与HDFS相关信息 副本数量 块大小 hdfs访问权限
yarn-site.xml 与yarn相关
mapred-site.xml 与mapred相关
3. 代码 *-site.xml 配置
4. 程序中
Configration.set()
#1. 如何生成公私钥对
[root@CentOS ~]# ssh-keygen -t rsa
#2.把client机的公钥,发送给远端主机
[root@CentOS ~]# ssh-copy-id CentOS
#3.测试连接
[root@CentOS ~]# ssh root@CentOS
#4.退出测试连接
[root@CentOS ~]# exit
NameNode在运行时,把重要的元数据放置在内存中,如果内存出现问题,则元数据丢失,为了保证元数据安全,NameNode有对应的持久化机制,把元数据持久化到硬盘存储。
持久化工作原理
fsimage:存储在Namenode服务所在物理主机磁盘上的一个二进制文本文件。记录了元数据信息
edits:存储在Namenode服务所在物理主机磁盘上的一个二进制文本文件,记录了对元数据修改操作。
#fsImage默认存储位置 /opt/install/hadoop-2.5.2/data/tmp/dfs/name
dfs.namenode.name.dir
#editslog默认存储位置
dfs.namenode.edits.dir
#定制FSImage和EditsLog的存储位置hdfs-site.xml
<property>
<name>dfs.namenode.name.dirname>
<value>file:///xxx/xxxxvalue>
property>
<property>
<name>dfs.namenode.edits.dirname>
<value>file:///xxx/xxxxvalue>
property>
HDFS集群启动经历过程
进入安全模式
1.整合 FSImage和EditsLog 生成新的EditsLog 和 FSImage,由新EditsLog接收用户写操作命令
2.DataNode都需NameNode主动汇报健康情况(心跳)3秒
3.汇报块列表 通过校验和 检查块是否可用,并定期1小时汇报。
当第一次启动Namenode服务的时候,系统会加载fsimage和edits文件进行合并得到最新元数据信息,并且更新fsimage和edits,一旦服务启动成功后,在服务允许期间不再更新fsimage,只是将操作记录在edits中。导致namenode在长期运行之后重启导致namenode启动时间过长,还可能导致edits文件过大。因此Hadoop HDFS引入Secondary Namenode 辅助Namenode在运行期间完成对元数据的备份和整理。
Secondary NameNode工作原理
自定义SecondaryNameNode 拉取数据的周期
hdfs-site.xml
dfs.namenode.checkpoint.period 3600秒
dfs.namenode.checkpoint.txns 1000000
secondaryNameNode启动方式:sbin/start-dfs.sh
sbin/hadoop-daemon.sh start secondarynamenode
定制secondaryNameNode 启动的节点
hdfs-site.xml
dfs.namenode.secondary.http-address 0.0.0.0:50090
dfs.namenode.secondary.https-address 0.0.0.0:50091
1. NameNode选择 内存大
2. DataNode选择 硬盘大
# namenode节点同时可以充当datanode,充分利用硬盘资源
ip地址 防火墙 selinux 主机名 主机映射 jdk ssh免密登陆
ssh免密登录:
1. 生成公私钥对
ssh-keygen -t rsa 最终放置到 ~/.ssh目录
2. 如何把client机的公钥,发送给远端主机
ssh-copy-id root@ip
1. Hadoop 每个节点都要安装hadoop,并且保证配置文件一致
注意:老机器化 删除 hadoop_home/data/tmp 内容
2. 按照分布式集群的要求,书写配置文件,同步集群的每一个节点
hadoop-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_71
core-site.xml
<property>
<name>fs.defaultFSname>
<value>hdfs://CentOSA:8020value>
property>
<property>
<name>hadoop.tmp.dirname>
<value>/opt/install/hadoop-2.5.2/data/tmpvalue>
property>
hdfs-site.xml
<property>
<name>dfs.permissions.enabledname>
<value>falsevalue>
property>
yarn-site.xml
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
mapred-site.xml
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
slaves
CentOSA
CentOSB
CentOSC
4. 格式化【namenode】
bin/hdfs namenode -format
5. 启动集群【namenode】
start-dfs.sh
stop-dfs.sh
#shell命令 执行在 namenode所在节点
1.1 解压缩
tar -zxvf zookeeper-3.4.5.tar.gz -C /opt/install
1.2 创建数据文件夹
mdkir zookeeper安装目录/data
1.3 conf目录修改zookeeper的配置文件
修改zoo_sample.cfg 为 zoo.cfg
mv zoo_sample.cfg zoo.cfg
编辑内容 vim zoo.cfg
dataDir=/opt/install/zookeeper-3.4.5/data
server.0=CentOSA:2888:3888
server.1=CentOSB:2888:3888
server.2=CentOSC:2888:3888
1.4 在每个节点zookeeper安装目录/data目录下创建myid文件(touch myid),并分别修改vim myid
CentOSA节点改为0
CentOSB节点改为1
CentOSC节点改为2
可用scp -r 命令 同步集群中所有节点 并 修改对应的myid文件
1.5 主节点 ssh 其他节点
ssh CentOSA
ssh CentOSB
ssh CentOSC
需要输入yes的节点需要再次ssh
每次ssh完毕后需要exit
1.6 启动zk服务
bin/zkServer.sh start | stop | restart
bin/zkServer.sh status 查看集群状态 【必须集群完整启动完成】
bin/zkCli.sh [leader]
☆☆☆删除 data/tmp
2.1 core-site.xml
fs.defaultFS
hdfs://ns
hadoop.tmp.dir
/opt/install/hadoop-2.5.2/data/tmp
ha.zookeeper.quorum
CentOSA:2181,CentOSB:2181, CentOSC:2181
2.2 hdfs-site.xml
dfs.permissions.enabled
false
dfs.nameservices
ns
dfs.ha.namenodes.ns
nn1,nn2
dfs.namenode.rpc-address.ns.nn1
CentOSA:8020
dfs.namenode.http-address.ns.nn1
CentOSA:50070
dfs.namenode.rpc-address.ns.nn2
CentOSB:8020
dfs.namenode.http-address.ns.nn2
CentOSB:50070
dfs.namenode.shared.edits.dir
qjournal://CentOSA:8485;CentOSB:8485;CentOSC:8485/ns
dfs.journalnode.edits.dir
/opt/install/hadoop-2.5.2/journal
dfs.ha.automatic-failover.enabled
true
dfs.client.failover.proxy.provider.ns
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
dfs.ha.fencing.methods
sshfence
dfs.ha.fencing.ssh.private-key-files
/root/.ssh/id_rsa
2.3 yarn-env.sh添加如下内容
export JAVA_HOME=/usr/java/jdk1.7.0_71
2.4启动命令
首先启动各个节点的Zookeeper,在各个节点上执行以下命令:(进程名 QuorumPeerMain-zookeeper集群进程)
bin/zkServer.sh start
在某一个namenode节点执行如下命令,创建命名空间
bin/hdfs zkfc -formatZK
在每个journalnode节点用如下命令启动journalnode(进程名JournalNode-同步EditsLog文件进程)
sbin/hadoop-daemon.sh start journalnode
在主namenode节点格式化namenode和journalnode目录
bin/hdfs namenode -format ns
在主namenode节点启动namenode进程(进程名NameNode)
sbin/hadoop-daemon.sh start namenode
在备namenode节点执行第一行命令,这个是把备namenode节点的目录格式化并把元数据从主namenode节点copy过来,并且这个命令不会把journalnode目录再格式化了!然后用第二个命令启动备namenode进程!
bin/hdfs namenode -bootstrapStandby
sbin/hadoop-daemon.sh start namenode(进程名NameNode)
在两个namenode节点都执行以下命令(进程名 DFSZKFailoverController-失败隔离控制进程 )
sbin/hadoop-daemon.sh start zkfc
在所有datanode节点都执行以下命令启动datanode(进程名 DataNode)
sbin/hadoop-daemon.sh start datanode
日常启停命令
sbin/start-dfs.sh
sbin/stop-dfs.sh
apache官方网站上提供的二进制文件,是基于32为操作系统进行编译的,不适合与64位操作系统,需要自己编译
1. hadoop源码
2. maven linux版本
3. 安装相关依赖软件
1. jdk
2. maven 并设置 环境变量 (apache-maven-3.0.5-bin.tar.gz)
/etc/profile
MAVEN_HOME
M2_HOME
PATH
3.linux相关的软件
yum install wget
yum install autoconf automake libtool cmake
yum install ncurses-devel
yum install openssl-devel
yum install lzo-devel zlib-devel gcc gcc-c++
4. 安装protobuf
解压:
tar -zxvf protobuf-2.5.0.tar.gz
编译安装:
进入安装目录,进行配置,执行命令:
./configure
分别执行安装命令:
make
make check
make install
5.安装findbugs
下载: findbugs-1.3.9.tar.gz
解压:
tar –zxvf findbugs-1.3.9.tar.gz
设置环境变量(/etc/profile):
export FINDBUGS_HOME=/opt/modules/findbugs-1.3.9
export PATH=$PATH:$ FINDBUGS_HOME/bin
执行命令:source /etc/profile
验证:findbugs -version
4. Hadoop源码编译
export MAVEN_OPTS="-Xms256m -Xmx512m"
mvn package -DskipTests -Pdist,native -Dtar 执行在Hadoop2.5.0的源码包中
5. 编译成功 hadoop_src_home/hadoop-dist/target
1. maven版本过高
2. 错误
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.7:run
(dist) on project hadoop-hdfs-httpfs: An Ant BuildException has occured: exec
returned: 2
[ERROR] around Ant part ...... @
10:134 in /home/pory/workplace/hadoop-2.4.1-src/hadoop-hdfs-project/hadoop-hdfshttpfs/target/antrun/build-main.xml
[ERROR] -> [Help 1]
这是因为/home/pory/workplace/hadoop-2.4.1-src/hadoop-hdfs-project/hadoop-hdfshttpfs/downloads目录下的文件没有下载完全,可以手动下一份匹配版本的文件放在下面,在
http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.36/bin/
然后重新执行命令
需要应用64为的hadoop替换32位hadoop /opt/install/hadoop-2.5.2/lib/native 的内容
# 替换一定在linux系统中直接替换。
Map Reduce是一个 Hadoop 的并行计算框架,借鉴了函数式编程(Scala 编程应用在Spark)思想和矢量编程(任务做阶段化拆分,每个阶段都可以设定并行度)。Hadoop 中是充分利用了存储节点(Data Node)运行所在主机的计算资源(CPU、内存、网络、少许磁盘-存储计算中间结果)完成对任务的并行计算。Map Reduce框架会在所有的DataNode所在的物理主机启动一个计算资源管理者-Node Manager用于管理本地的计算资源,默认系统会将计算资源均分8个等份,每个等份抽象成一个Container。还会再找一些其他的主机启动一个资源管理中心-Resource Manager,用于管理集群的计算资源。
当用户提交一个计算任务给MapReduce框架,框架会将任务拆分成Map阶段和Reduce阶段(矢量编程思想将任务拆分成两个阶段),框架会根据Map/Reduce阶段的任务并行度.在任务提交初期会启动一个任务管理者(每个任务都有自己的任务管理者)-MRAppMaster(该进程会浪费掉1个计算资源)用于管理Map阶段和Reduce阶段任务执行。在任务执行时期,每个阶段会根据阶段任务的并行度分配计算资源(每个计算资源启动一个Yarn Child),由MRAppMaster完成对阶段任务的检测管理。
MapReduce的构建思想
MapReduce的执行过程
ResourceManager:负责任务资源的统一调度,管理NodeManager资源,启动MRAppMaster
NodeManager:用于管理本机上的计算资源,默认会将本机的计算资源拆分为8个等份,每个等份抽象成Container
MRAppMaster:任何一个执行的任务都会有一个MRAppMaster负责YarnChild任务的执行和监测。
YarnChild:是具体执行的MapTask或者是ReduceTask的统称。
任务执行期间系统会启动MRAppmaster和YarnChild负责任务的执行,一旦任务执行结束MRAppMaster和YarnChild会自动退出。
1. 配置相关的配置文件 etc/hadoop
yarn-site.xml mapred-site.xml
2. 启动yarn
2.1 伪分布式
sbin/yarn-daemon.sh start resourcemanager
sbin/yarn-daemon.sh start nodemanager
2.2 集群方式
mapred-site.xml
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
yarn-site.xml
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
<property>
<name>yarn.resourcemanager.hostnamename>
<value>CentOSB.baizhiedu.comvalue>
property>
slaves
datanode同时又是nodemanager
同步集群的每一个节点
正常启动hdfs
namenode格式化
sbin/start-dfs.sh
集群方式的yarn启动
建议 namenode 不要和 resourcemanager放置在同一个点
# ssh相关的机器,避免yes
在集群环境下,yarn启动的命令,需要在resourcemanager所在的节点执行
sbin/start-yarn.sh
sbin/stop-yarn.sh
验证:
jps看进程
http://CentOSB:8088
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-mapreduce-client-jobclientartifactId>
<version>2.6.0version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-mapreduce-client-coreartifactId>
<version>2.6.0version>
dependency>
日志级别 URL 用户ID 日期
INFO /product 001 2019-03-26 10:00:00
INFO /cart 003 2019-03-26 10:00:00
INFO /product 001 2019-03-26 10:00:00
INFO /cart 002 2019-03-26 10:00:00
INFO /order 004 2019-03-26 10:00:00
1.按照URL统计每个板块访问的次数,并且使用柱状图显示?
商品板块 2
购物车 2
create table t_click(
level varchar(32),
url varchar(128),
uid varchar(32),
click_time timestamp
)
select url,sum(1) from t_click group by url
reduce(key,values) map(key,value)
reduce(url,[1,1,1,...]) map(url,1)
public class ClickMappper extends Mapper<LongWritable, Text,Text, IntWritable> {
//INFO /product 001 2019-03-26 10:00:00
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] tokens = value.toString().split(" ");
context.write(new Text(tokens[1]),new IntWritable(1));
}
}
public class ClickReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int total=0;
for (IntWritable value : values) {
total=value.get();
}
context.write(key,new IntWritable(total));
}
}
public class CustomJobSubmitter extends Configured implements Tool {
public int run(String[] strings) throws Exception {
//1.封装Job对象
Job job=Job.getInstance(getConf());
//2.设置任务的读取、写出数据格式
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
//3.设置数据读入和写出路径
Path src = new Path("/demo/click");
TextInputFormat.addInputPath(job,src);
Path dst = new Path("/demo/result");//必须不存在,否则任务提交失败
TextOutputFormat.setOutputPath(job,dst);
//4.设置数据处理逻辑代码片段
job.setMapperClass(ClickMappper.class);
job.setReducerClass(ClickReducer.class);
//5.设置Mapper和Reducer输出key-value类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.任务提交
//job.submit();
job.waitForCompletion(true);
return 0;
}
public static void main(String[] args) throws Exception {
ToolRunner.run(new CustomJobSubmitter(),args );
}
}
远程jar发布
job.setJarByClass(CustomJobSubmitter.class);
hadoop jar xxxxx.jar com.baizhi.CustomJobSubmitter
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-jar-pluginartifactId>
<version>2.3.2version>
<configuration>
<outputDirectory>${basedir}outputDirectory>
<archive>
<manifest>
<mainClass>${baizhi-mainClass}mainClass>
manifest>
archive>
configuration>
plugin>
<extensions>
<extension>
<groupId>org.apache.maven.wagongroupId>
<artifactId>wagon-sshartifactId>
<version>2.8version>
extension>
extensions>
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>wagon-maven-pluginartifactId>
<version>1.0version>
<configuration>
<fromFile>${project.build.finalName}.jarfromFile>
<url>scp://root:123456@${target-host}${target-position}url>
<commands>
<command>pkill -f ${project.build.finalName}.jarcommand>
<command>nohup /opt/install/hadoop-2.5.2/bin/yarn jar ${target-position}/${project.build.finalName}.jar > /root/nohup.out 2>&1 &command>
commands>
<displayCommandOutputs>truedisplayCommandOutputs>
configuration>
plugin>
jar:jar wagon:upload wagon:sshexec
public static boolean access(String path, NativeIO.Windows.AccessRight desiredAccess) throws IOException {
return true;
//return access0(path, desiredAccess.accessRight());
}
//设置配置信息
conf.addResource("core-site.xml");
conf.addResource("hdfs-site.xml");
conf.addResource("yarn-site.xml");
conf.addResource("mapred-site.xml");
conf.set("mapreduce.job.jar","file:///jar包路径");
程序员根据自己的需求,定义Maven Archetype(骨架),后续选择自定义的骨架,就可以把我们需要的pom,其他配置文件,代码的骨架,自动生成,简化开发与测试
- 创建一个模板module
1. 引入相关jar的坐标 2. 创建Java代码 在本项目的根下:mvn --settings F:\apache-maven-3.3.9\conf\settings.xml archetype:create-from-project
- 复制骨架的坐标(便于后续的安装)
com.baizhiedu hadoop-test-archetype 1.0-SNAPSHOT
- 安装骨架
cd target\generated-sources\archetype mvn clean install
- 创建项目并引入骨架
需要指定骨架的坐标,来源第二步。
- 建议MR代码中通过Log4进行调试
Logger logger = Logger(xxx.class); logger.info() 通过上述操作 输出的结果,只能查看job的信息,而Map,Reduce的信息看不到。 需要开启Yarn 历史日志 ,日志归档
- yarn集群中如何开启历史日志,日志归档
1. 配置文件 mapred-site.xml 历史服务
mapreduce.jobhistory.address hadoop12.baizhiedu.com:10020 yarn-site.xml 日志聚合 mapreduce.jobhistory.webapp.address hadoop12.baizhiedu.com:19888 yarn.log-aggregation-enable true 2. 启动进程 sbin/mr-jobhistory-daemon.sh start historyserver sbin/mr-jobhistory-daemon.sh stop historyserver yarn.log-aggregation.retain-seconds 604800
实战
应用shell脚本 解决关闭日志聚合
etc/hadoop/yarn-env.sh
export YARN_LOG_DIR=~/logs/yarn export YARN_PID_DIR=~/data/yarn
创建脚本
if [ $# -le 0 ] then echo 缺少参数 exit 1 fi logtype=out if [ $# -ge 1 ] then logtype=${2} fi for n in `cat /opt/install/hadoop-2.5.2/etc/hadoop/slaves` do echo ===========查看节点 $n============ ssh $n "cat ~/logs/yarn/userlogs/${1}/container_*/*${logtype}|grep com.baizhiedu" done
运行脚本
1. 修改脚本权限 2. ./scanMRLog.sh application_1558968514803_0001
~~~
对接文件系统-(读取):
切片计算 :以文件为单位,对一个文件按照SplitSize计算切片大小(0~140.8 MB)
Key-Value : 行字节偏移量LongWritable | 当前文本行 ,确定Mapper
切片计算 :以文件为单位,对一个文件按照行切割,默认是1行一个切片
Key-Value : 行字节偏移量LongWritable | 当前文本行 ,确定Mapper
mapreduce.input.lineinputformat.linespermap = 10000
切片计算 :以文件为单位,对一个文件按照SplitSize计算切片大小(0~140.8 MB)
Key-Value : Text \t Text ,确定Mapper
mapreduce.input.keyvaluelinerecordreader.key.value.separator=|
切片计算 :对N个文件按照SplitSize计算切片大小(0~140.8 MB),多个文件对应一个切片
Key-Value :行字节偏移量LongWritable | 当前文本行 ,确定Mapper
1、在Map端分别对不同格式的数据定制Mapper和InputFormat
2、所有的Mapper输出KEY-VALUE必须保证一致
3、所有Map输出的KEY必须是 join 字段
4、针对不同的Mapper输出,通过对值做标记,这样才可以在Reduce端区分数据
//1.配置数据链接参数
DBConfiguration.configureDB(conf,
"driver",
"url",
"username",
"password"
);
//2.设置任务的写出数据格式
job.setOutputFormatClass(DBOutputFormat.class);
//3.设置数据写出路径
DBOutputFormat.setOutput(job,"t_user_order","id","name","age","items","price");
//4.Reduce端输出的Key类型必须实现DBWritable接口
job.setOutputKeyClass(Class<? extends DBWritable>);
Writable和DBWritable用法
Writable
:当自定义Map端输出Value类型,必须实现Writable接口,因为框架将会对Map的输出做本地磁盘的序列化。如果用户需要自定义Map端输出key类型,和值类型相比较多个排序的需求因此如果用户需要自定map端的输出key类型,必须实现WritableComparable接口。
DBWriteable
:当用户使用DBOutputFormat时候,强制要求Reducer端的输出key类型必须实现DBWriteable接口,此时需要用户实现write方法给?赋值。通过使用DBOutputFormat可以获知,Reducer端输出的Key-Value类型所限与用户使用的OutputFormat。因此Reduce端的输出key-value类型和Writable接口没有任何关系。
方案1
要求用户将依赖的jar包拷贝给所有的计算节点(NodeManager运行所在主机)
[root@CentOS ~]# hadoop jar xxx.jar 入口类 -libjars 依赖jar包1,依赖jar包2,…
1
方案2
[root@CentOS ~]# hdfs dfs -mkdir /libs
[root@CentOS ~]# hdfs dfs -put mysql-connector-java-5.1.46.jar /libs
conf.setStrings(“tmpjars”,"/libs/xxx1.jar,/libs/xxx2.jar,…");
需要用户配置HADOOP_CLASSPATH环境变量(/root/.bashrc),通常这种依赖发生在切片计算阶段。
HADOOP_CLASSPATH=/root/mysql-connector-java-5.1.46.jar
export HADOOP_CLASSPATH
[root@CentOS ~]# source .bashrc
[root@CentOS ~]# hadoop classpath #查看hadoop的类路径
/usr/hadoop-2.6.0/etc/hadoop:/usr/hadoop-2.6.0/share/hadoop/common/lib/*:/usr/hadoop-2.6.0/share/hadoop/common/*:/usr/hadoop-2.6.0/share/hadoop/hdfs:/usr/hadoop-2.6.0/share/hadoop/hdfs/lib/*:/usr/hadoop-2.6.0/share/hadoop/hdfs/*:/usr/hadoop-2.6.0/share/hadoop/yarn/lib/*:/usr/hadoop-2.6.0/share/hadoop/yarn/*:/usr/hadoop-2.6.0/share/hadoop/mapreduce/lib/*:/usr/hadoop-2.6.0/share/hadoop/mapreduce/*:`/root/mysql-connector-java-5.1.46.jar`:/usr/hadoop-2.6.0/contrib/capacity-scheduler/*.jar
案例参考 DBInputFormat案例。
job.waitForCompletion(true);
submit
final JobSubmitter submitter = getJobSubmitter(fs, yarn);
submitter.submitJobInternal(Job.this, cluster);
checkSpecs(job);//检查输出目录是否为null
JobID jobId = submitClient.getNewJobID();//获取jobid
copyAndConfigureFiles(job, submitJobDir);//拷贝代码片段以及依赖jars
int maps = writeSplits(job, submitJobDir);//计算切片
writeConf(conf, submitJobFile);//生成job.xml
submitClient.submitJob(jobId, submitJobDir,...);
ApplicationSubmissionContext appContext =
createApplicationSubmissionContext(conf, jobSubmitDir, ts);//构建MR AP所需信息
resMgrDelegate.submitApplication(appContext);//任务提交
public class RedisOutpoutFormat extends OutputFormat<String,String> {
public RecordWriter<String, String> getRecordWriter(TaskAttemptContext context) throws IOException, InterruptedException {
Configuration conf = context.getConfiguration();
RedisConfiguration redisConf = new RedisConfiguration(conf);
return new RedisHashRecordWriter(redisConf.getHost(),redisConf.getPort(),redisConf.getDescriptKey());
}
public void checkOutputSpecs(JobContext context) throws IOException, InterruptedException { }
public OutputCommitter getOutputCommitter(TaskAttemptContext context) throws IOException, InterruptedException {
return new FileOutputCommitter(FileOutputFormat.getOutputPath(context),
context);
}
}
public class RedisHashRecordWriter extends RecordWriter<String,String> {
private Jedis jedis;
private String descriptKey;
private Pipeline pipeline;
public RedisHashRecordWriter(String host,int port,String descriptKey) {
this.jedis = new Jedis(host,port);
pipeline=jedis.pipelined();
this.descriptKey=descriptKey;
}
public void write(String key, String value) throws IOException, InterruptedException {
//启用Redis的批处理
pipeline.hset(descriptKey,key,value);
}
public void close(TaskAttemptContext context) throws IOException, InterruptedException {
pipeline.sync();//批量提交
jedis.close();//关闭链接
}
}
public class RedisConfiguration {
private Configuration conf;
public RedisConfiguration(Configuration conf) {
this.conf = conf;
}
public static final String REDIS_HOST="redis.host";
public static final String REDIS_PORT="redis.port";
public static final String REDIS_DESCRIPT_KEY="redis.descriptKey";
public static void configRedis(Configuration conf,String host,int port,String descriptKey){
conf.set(REDIS_HOST,host);
conf.setInt(REDIS_PORT,port);
conf.set(REDIS_DESCRIPT_KEY,descriptKey);
}
public String getHost(){
return conf.get(REDIS_HOST);
}
public int getPort(){
return conf.getInt(REDIS_PORT,6379);
}
public String getDescriptKey(){
return conf.get(REDIS_DESCRIPT_KEY);
}
}
public class CustomJobSubmitter extends Configured implements Tool {
public int run(String[] strings) throws Exception {
//1.封装Job对象\
Configuration conf = getConf();
RedisConfiguration.configRedis(conf,
"CentOS",
6379,
"url_click");
Job job=Job.getInstance(conf);
//2.设置任务的读取、写出数据格式
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(RedisOutpoutFormat.class);
//3.设置数据读入和写出路径
Path src = new Path("file:///D:/demo/click");
TextInputFormat.addInputPath(job,src);
//4.设置数据处理逻辑代码片段
job.setMapperClass(ClickMappper.class);
job.setReducerClass(ClickReducer.class);
//5.设置Mapper和Reducer输出key-value类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(String.class);
job.setOutputValueClass(String.class);
//6.任务提交
//job.submit();
job.waitForCompletion(true);
return 0;
}
public static void main(String[] args) throws Exception {
ToolRunner.run(new CustomJobSubmitter(),args );
}
}
public class CustomJobSubmitter extends Configured implements Tool {
public int run(String[] strings) throws Exception {
//1.封装Job对象
Job job=Job.getInstance(getConf());
//2.设置任务的读取、写出数据格式
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
//3.设置数据读入和写出路径
Path src = new Path("file:///D:/demo/click");
TextInputFormat.addInputPath(job,src);
Path dst = new Path("file:///D:/demo/result");//必须不存在,否则任务提交失败
TextOutputFormat.setOutputPath(job,dst);
//4.设置数据处理逻辑代码片段
job.setMapperClass(ClickMappper.class);
//5.设置Mapper和Reducer输出key-value类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setNumReduceTasks(0);//设置NumReducecTask 0
//6.任务提交
//job.submit();
job.waitForCompletion(true);
return 0;
}
public static void main(String[] args) throws Exception {
ToolRunner.run(new CustomJobSubmitter(),args );
}
}
job.setPartitionerClass(…)
分区内部有序,默认按照Map端输出key的升序
是因为选取的Key不合理,到时分区数据分布不均匀。在任务计算第二阶段Reduce计算带来压力。
Map端并行度是通过计算任务切片决定的,Reduce端是通过job.setNumReduceTask(n)
1.避免小文件计算,适当线下合并
2.调整环装缓冲区的参数,减少Map任务的IO操作
3.开启Map段压缩conf.setBoolean("mapreduce.map.output.compress",true); conf.setClass("mapreduce.map.output.compress.codec", GzipCodec.class, CompressionCodec.class);
4.如果条件允许,可以考虑在Map端预执行Reduce逻辑-Map端的Combiner
是一种针对Mapshuffle的优化,主要是通过在Map端本地支持局部Reduce操作,该操作可以极大减轻网络IO占用,减少key的排序量,但是并不是所有的操作都支持Combiner:
- Combiner默认不会开启,需要程序员编码设置
- 要求Combiner不可以改变Map端最终的输出key-value类型(Combiner输入和输出类型一致)
- 必须满足计算支持迭代,例如:求和、最大值、最小值 ,但是 平均值就不适用
job.setCombinerClass(ClickCombiner.class);public class ClickCombiner extends Reducer<Text, IntWritable,Text,IntWritable> { @Override protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { System.out.println("--ClickCombiner---"); int total=0; for (IntWritable value : values) { total += value.get() ; } context.write(key,new IntWritable(total)); } }
5.适当调整NodeManager管理Container的个数和内存大小
yarn.nodemanager.resource.cpu-vcores = 8 yarn.nodemanager.resource.memory-mb = 8192
网络日志清洗数据 ETL (Extract Transfer Load),一般这种操作不需要Reduce即可完成
基于大数据数据统计和报表 求最大、求最小、求平均 使用柱状图、饼状图展示。
画像生成-为后续AI学习提供计算所需数据模型 特征向量 线性回归|逻辑回归
个性化推荐 通过MapReduce 生成算法所需数据样本
基于用户的协同推荐算法
基于物品协同过滤算法(比较多)
数据格式(MapReduce ETL或者统计得来)
userid/itemid/score
1,101,5.0
1,102,3.0
1,103,2.5
2,101,2.0
2,102,2.5
2,103,5.0
2,104,2.0
3,101,2.5
3,104,4.0
3,105,4.5
3,107,5.0
4,101,5.0
4,103,3.0
4,104,4.5
4,106,4.0
5,101,4.0
5,102,3.0
5,103,2.0
5,104,4.0
5,105,3.5
5,106,4.0
[root@CentOS ~]# tar -zxf apache-mahout-distribution-0.13.0.tar.gz -C /usr/
[root@CentOS ~]# hadoop jar /usr/apache-mahout-distribution-0.13.0/mahout-mr-0.13.0-job.jar org.apache.mahout.cf.taste.hadoop.item.RecommenderJob --input /recomand --output /recomand-out -s SIMILARITY_LOGLIKELIHOOD
1 [104:2.8088317,106:2.5915816,105:2.5748677]
2 [105:3.5743618,106:3.3991857]
3 [103:4.336442,106:4.0915813,102:4.0915813]
4 [102:3.6903737,105:3.6903737]
5 [107:3.663558]
安装三台CentOS-6.5 64 bit操作系统(完成JDK、SSH免密码认证、IP主机名映射、关闭防火墙等工作)
主机和服务启动映射表
主机 服务
CentOSA NameNode、zkfc、DataNode、JournalNode、Zookeeper、NodeManager
CentOSB NameNode、zkfc、DataNode、JournalNode、Zookeeper、NodeManager、ResourceManager
CentOSC DataNode、JournalNode、Zookeeper、NodeManager、ResourceManager
主机信息
主机名 IP信息
CentOSA 192.168.40.129
CentOSB 192.168.40.130
CentOSC 192.168.40.131
JDK安装和配置
[root@CentOSX ~]# rpm -ivh jdk-8u171-linux-x64.rpm
[root@CentOSX ~]# vi .bashrc
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.
export JAVA_HOME
export CLASSPATH
export PATH
[root@CentOSX ~]# source .bashrc
IP主机名映射
[root@CentOSX ~]# vi /etc/hosts
192.168.40.129 CentOSA
192.168.40.130 CentOSB
192.168.40.131 CentOSC
关闭防火墙
[root@CentOSX ~]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter [ OK ]
iptables: Flushing firewall rules: [ OK ]
iptables: Unloading modules: [ OK ]
[root@CentOSX ~]# chkconfig iptables off
SSH免密码认证
[root@CentOSX ~]# ssh-keygen -t rsa
[root@CentOSX ~]# ssh-copy-id CentOSA
[root@CentOSX ~]# ssh-copy-id CentOSB
[root@CentOSX ~]# ssh-copy-id CentOSC
Zookeeper
[root@CentOSX ~]# tar -zxf zookeeper-3.4.6.tar.gz -C /usr/
[root@CentOSX ~]# mkdir /root/zkdata
[root@CentOSA ~]# echo 1 >> /root/zkdata/myid
[root@CentOSB ~]# echo 2 >> /root/zkdata/myid
[root@CentOSC ~]# echo 3 >> /root/zkdata/myid
[root@CentOSX ~]# touch /usr/zookeeper-3.4.6/conf/zoo.cfg
[root@CentOSX ~]# vi /usr/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
dataDir=/root/zkdata
clientPort=2181
initLimit=5
syncLimit=2
server.1=CentOSA:2887:3887
server.2=CentOSB:2887:3887
server.3=CentOSC:2887:3887
[root@CentOSX ~]# /usr/zookeeper-3.4.6/bin/zkServer.sh start zoo.cfg
[root@CentOSX ~]# /usr/zookeeper-3.4.6/bin/zkServer.sh status zoo.cfg
JMX enabled by default
Using config: /usr/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode: `follower|leader`
[root@CentOSX ~]# jps
5879 `QuorumPeerMain`
7423 Jps
解压并配置HADOOP_HOME
[root@CentOSX ~]# tar -zxf hadoop-2.6.0_x64.tar.gz -C /usr/
[root@CentOSX ~]# vi .bashrc
HADOOP_HOME=/usr/hadoop-2.6.0
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
CLASSPATH=.
export JAVA_HOME
export CLASSPATH
export PATH
export HADOOP_HOME
[root@CentOSX ~]# source .bashrc
配置core-site.xml
<property>
<name>fs.defaultFSname>
<value>hdfs://myclustervalue>
property>
<property>
<name>hadoop.tmp.dirname>
<value>/usr/hadoop-2.6.0/hadoop-${user.name}value>
property>
<property>
<name>fs.trash.intervalname>
<value>30value>
property>
<property>
<name>net.topology.script.file.namename>
<value>/usr/hadoop-2.6.0/etc/hadoop/rack.shvalue>
property>
<property>
<name>ha.zookeeper.quorumname>
<value>CentOSA:2181,CentOSB:2181,CentOSC:2181value>
property>
<property>
<name>dfs.ha.fencing.methodsname>
<value>sshfencevalue>
property>
<property>
<name>dfs.ha.fencing.ssh.private-key-filesname>
<value>/root/.ssh/id_rsavalue>
property>
配置机架脚本
[root@CentOSX ~]# touch /usr/hadoop-2.6.0/etc/hadoop/rack.sh
[root@CentOSX ~]# chmod u+x /usr/hadoop-2.6.0/etc/hadoop/rack.sh
[root@CentOSX ~]# vi /usr/hadoop-2.6.0/etc/hadoop/rack.sh
while [ $# -gt 0 ] ; do
nodeArg=$1
exec</usr/hadoop-2.6.0/etc/hadoop/topology.data
result=""
while read line ; do
ar=( $line )
if [ "${ar[0]}" = "$nodeArg" ] ; then
result="${ar[1]}"
fi
done
shift
if [ -z "$result" ] ; then
echo -n "/default-rack"
else
echo -n "$result "
fi
done
[root@CentOSX ~]# touch /usr/hadoop-2.6.0/etc/hadoop/topology.data
[root@CentOSX ~]# vi /usr/hadoop-2.6.0/etc/hadoop/topology.data
192.168.40.129 /rack01
192.168.40.130 /rack01
192.168.40.131 /rack03
配置hdfs-site.xml
<property>
<name>dfs.replicationname>
<value>3value>
property>
<property>
<name>dfs.ha.automatic-failover.enabledname>
<value>truevalue>
property>
<property>
<name>dfs.nameservicesname>
<value>myclustervalue>
property>
<property>
<name>dfs.ha.namenodes.myclustername>
<value>nn1,nn2value>
property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1name>
<value>CentOSA:9000value>
property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2name>
<value>CentOSB:9000value>
property>
<property>
<name>dfs.namenode.shared.edits.dirname>
<value>qjournal://CentOSA:8485;CentOSB:8485;CentOSC:8485/myclustervalue>
property>
<property>
<name>dfs.client.failover.proxy.provider.myclustername>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvidervalue>
property>
配置slaves
CentOSA
CentOSB
CentOSC
启动HDFS(集群初始化启动)
[root@CentOSX ~]# hadoop-daemon.sh start journalnode (等待10s钟)
[root@CentOSA ~]# hdfs namenode -format
[root@CentOSA ~]# hadoop-daemon.sh start namenode
[root@CentOSB ~]# hdfs namenode -bootstrapStandby
[root@CentOSB ~]# hadoop-daemon.sh start namenode
#注册Namenode信息到zookeeper中,只需要在CentOSA或者B上任意一台执行一下指令
[root@CentOSA|B ~]# hdfs zkfc -formatZK
[root@CentOSA ~]# hadoop-daemon.sh start zkfc
[root@CentOSB ~]# hadoop-daemon.sh start zkfc
[root@CentOSX ~]# hadoop-daemon.sh start datanode
查看机架信息
[root@CentOSB ~]# hdfs dfsadmin -printTopology
Rack: /rack01
192.168.40.129:50010 (CentOSA)
192.168.40.130:50010 (CentOSB)
Rack: /rack03
192.168.40.131:50010 (CentOSC)
yarn-site.xml
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
<property>
<name>yarn.resourcemanager.ha.enabledname>
<value>truevalue>
property>
<property>
<name>yarn.resourcemanager.cluster-idname>
<value>clustervalue>
property>
<property>
<name>yarn.resourcemanager.ha.rm-idsname>
<value>rm1,rm2value>
property>
<property>
<name>yarn.resourcemanager.hostname.rm1name>
<value>CentOSBvalue>
property>
<property>
<name>yarn.resourcemanager.hostname.rm2name>
<value>CentOSCvalue>
property>
<property>
<name>yarn.resourcemanager.zk-addressname>
<value>CentOSA:2181,CentOSB:2181,CentOSC:2181value>
property>
mapred-site.xml
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
启动|关闭Yarn服务
[root@CentOSB ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSC ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSX ~]# yarn-daemon.sh start|stop nodemanger