学习内容地址:https://www.bilibili.com/video/av23858681?from=search&seid=15317487379960135161
Linux是一套免费使用和自由传播的Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。
基本思想
Linux的基本思想有两点:1. 一切都是文件;2. 每个软件都有确定的用途。
完全免费
完全兼容POSIX1.0标准
多用户和多任务
一般的界面
支持多种平台
Linux是一个免费的像windows一样的操作系统
linux中几乎一起都是文件,文件几乎没有后缀区分
Linux中有且仅有一个超级用户
Linux一般作为服务器
WMWare下载地址:https://www.cr173.com/soft/68480.html
下载完毕直接进行安装。
安装步骤中需要密钥的时候在百度上搜索可以得到很多密钥:https://blog.csdn.net/QS_1024/article/details/78277030
常用目录 | 作用 |
---|---|
/ | Linux系统的根目录,一般用于存放目录 |
/etc | 系统级别的配置文件存放的目录,一般由配置管理员来使用 |
/home | 所有普通用户的家目录 |
/root | root用户的根目录 |
/tmp | 存放应用程序产生的临时数据,不能在此目录存放重要数据 |
/var | 系统一般运行时需要改变的数据 |
/usr | 应用程序相关目录命令、函数库、共享包、内核源码 |
我下载的是本文中给出来连接的系统,和老师讲解的系统存在一定的差异性。最大的差异就是我这里只有命令行的模式,所以这里的网络配置肯定不能照着老师来执行。
参考文章:https://www.cnblogs.com/xixihuang/p/5404517.html
这里我参考了上篇文章中命令模式的方法。
nmcli d
vi xxx
BOOTPROTO=dhcp ONBOOT=yes
systemctl restart network
ping www.baidu.com
CentOS7 Failed to start LSB: Bring up/down解决方法
参考:http://www.mamicode.com/info-detail-2072502.html
解决办法:
停止NetworkManager服务
停止
[root@client01 network-scripts]# systemctl stop NetworkManager
取消开机启动
[root@client01 network-scripts]# systemctl disable NetworkManager
重启网络
[root@client01 network-scripts]# service network restart
Restarting network (via systemctl): [ OK ]
至此,问题解决
第一次想查看本机ip的时候,输入ifconfig显示没有该命令,所以需要从网络中下载。为此上一个步骤成功联网后才能在这一步执行所需操作:yum -y install net-tools
常用命令 | 作用 |
---|---|
man | 帮助命令 |
ctrl+R | 查找历史输入的命令 |
CTRL+z | 退出或者终止 |
单击tab | 补全 |
双击tab | 显示以输入字符开始的所有名称 |
q | 退出 |
vi | 编辑 |
cat | 将某个文档的内容显示出来 |
pwd | 查看当前目录 |
alias | 创建命令的临时别名 |
系统级别命令 | 作用 |
---|---|
ifconfig | 查看ip等 |
uname | 查看系统信息 |
ps -ef | 查看系统的进程 |
top | 系统进程和运行情况 |
grep | 过滤 |
reboot | 重启启动Liux操作系统 |
shutdown | 关闭Linux操作系统 |
kill | 杀死一个进程 |
磁盘操作命令 | 作用 |
---|---|
df -h | 显示磁盘的分区信息 |
fdisk -l | 详细磁盘分区信息 |
du -h -s | 查看目录的使用大小 |
mount -t | 挂载 |
umount | 卸载 |
fsck | 修复磁盘 |
Linux磁盘格式:ext4、ext3、ext2、vfat(fat32)
账户 | uid |
---|---|
超级账户 | 0 |
普通账户 | >=500 |
系统账户 | 1~499 |
/etc/passwd | 保存账户的信息 |
/etc/shadow | 保存账户的密码信息 |
/root | root用户家目录 |
/home/xxx | 普通用户xxx家目录 |
函数 | 用法 |
---|---|
useradd | 创建用户,如果是第一次创建就会创建一个相同名称的组 |
-u | 指定uid |
-d | 指定宿主目录 |
-s | 指定使用shell |
-e | 指定用户过期时间 |
-g | 指定基本组 |
-G | 指定附加组 |
gpasswd -a openlab groupenlab | 将用户加入到指定组 |
gpasswd -d openlab groupenlab | 将用户从组中删除 |
echo “123456” | passwd --stdin feige | 不通过交互信息,直接修改用户密码 |
userdel | 删除用户不删除用户文件 |
userdel -r | 连主目录一起删除 |
id openlab | 显示用户信息 |
函数 | 用法 |
---|---|
groupadd | 单独创建一个组 |
groups manager | 查看用户在哪些组 |
useradd -G manager tom | 创建用户时附加到组 |
su -xxx | 切换当前用户为xxx |
whoami | 显示当前登陆用户账户 |
cat | 查看文件信息 |
函数 | 用法 |
---|---|
mkdir /tmp/test01 | 创建空的文件夹 |
mkdir -p /data1/hadoop/ddfs/name | 创建递归文件夹 |
touch /tmp/test01/file.txt | 创建空文件 |
vi file.log | 创建空文件并进入编辑模式 |
echo"123" >>file.txt | 创建file.txt并输入字符串到该文件(如果存在一个>为重写,两个>>为追加) |
echo “123” | 屏幕打印123 |
函数 | 用法 |
---|---|
vi | 进入文件编辑器。i进入编辑模式;esc退出编辑模式; |
:w | 保存 |
:q | 退出 |
:wq | 保存并退出 |
:q! | 强制性退出 |
函数 | 用法 |
---|---|
cat -n | 查看时显示行号 |
cat | 不显示行号 |
tail -n | (默认10行)从后往前读取n行,有监控文档的用途 |
head -n | (默认10行)从前往后读取n行,有监控文档的用途 |
More : | 百分比查看,不能回滚看 |
Less : | 能往回滚看 |
函数 | 用法 |
---|---|
cp /tmp/file.txt /opt | 将tmp目录下的file文件复制到opt目录下 |
cp -r /tmp/test01 /opt | 将temp目录下的test01目录复制到opt目录下 |
mv /tmp/file /opt | 将file文件或目录剪切到opt目录里面(也可以进行重命名的操作) |
rename | 批量重名名 |
函数 | 用法 |
---|---|
rm | 删除一个文件 |
rm -rf | 强制递归删除 |
####4.2.7 打包压缩、查找
10. 打包tar
参数 | 用法 |
---|---|
-z | 压缩 |
-c | 打包 |
-x | 解包 |
-f | 必须要 |
-C | 指定解包位置 |
-v | 输出信息 |
/usr/bin/zip | |
/usr/bin/unzip | |
/bin/gzip | |
/bin/gunzip | |
tar -zcvf ./test.tar ./test/ | 将当前目录下的test文件夹打包成test.tat包 |
tar -zxvf ./test.tar | 将当前目录下的tar包进行解压 |
tar -zxvf ./test.tar -C /root/Desktop/ | 将压缩包解压到root中的desktop目录 |
函数 | 用法 |
---|---|
which cmd | 查找cmd命令所在路径 |
whereis cmd | 查找cmd命令的安装路径 |
locate | 文件查找-效率很快(实质是查找数据库) |
find -name xxx | 根据名称类型来进行查找 |
函数 | 用法 |
---|---|
alias cle=clear | 设置clear的别名为cle,但仅临时有效 |
进入vi ~/.bashrc,添加alias cle=“clear” | 文件中修改,永久有效,但仅针对当前用户 |
~ | 当前目录 |
cd - | 退回到上一次的目录 |
cd …/ | 退回到上一层目录 |
cd …/… | 退回到上上层目录 |
cd ./ | 当前目录 |
安装
安装 | 用法 |
---|---|
yum install | 安装全部 |
yum install package1 | 安装指定的程序包 |
yum groupinstall group1 | 安装程序包group1 |
更新
更新 | 用法 |
---|---|
yum -y update | 升级所有包,改变软件设置和系统设置,系统版本内核都升级 |
yum -y upgrade | 升级所有报,不改变软件设置和系统设置,系统版本升级,内核不改变 |
yum update package1 | 更新指定程序包package |
yum check-update | 检查可更新的程序 |
yum upgrade package1 | 升级指定程序包package1 |
yum groupupdate group1 | 升级程序组goup1 |
查找和显示
更新 | 用法 |
---|---|
yum info package1 | 显示安装包的信息 |
yum list | 显示所有已经安装和可安装的程序包 |
yum list package | 显示指定程序包安装情况 |
yum groupinfo group1 | 显示程序组1的信息 |
yum grouplist | 显示所有的可以安装和已经安装的组 |
yum search string | 根据关键字string查找安装包 |
删除程序
删除 | 用法 |
---|---|
yum -y remove/erase package1 | 删除程序包package1 |
yum groupremove group1 | 删除程序组group1 |
yum deplist package1 | 查看程序package依赖情况 |
清除缓存
清除 | 用法 |
---|---|
yum clean packages | 清除缓存目录下的软件包 |
yum clean headers | 清除缓存目录下的headers |
yum clean oldheaders | 清除缓存目录下旧的headers |
yum clean,yum clean all | 清除缓存目录下的软件包和旧的headers |
yum makecache | 重新构建缓存 |
shell是一个用c语言编写的程序,被称为用户使用linux的桥梁
shell既是一个命令语言,也是一个程序设计语言
shell脚本(shell script),是一种为shell编写的脚本程序
shell编程和java,python等一样,只需要一个文本编辑器和解释工具即可
运行方式:而可执行权限运行 chmod a+x /home/shell/first…sh使脚本具有可执行的权限;加解释器运行/bin/bash /home/shell/first.sh
bash支持一维数组,并没有限定数组的大小。和C语言类似,数组元素的下标是从0开始的。
以“#”开头的行就是注释,会被解释器忽略。sh里没有多行注释,只能每一行加#。如果大段代码需要注释,可以把这一段代码用一个花括号括起来,定义为一个函数,没有地方调用这个函数就和注释一样的效果。
数学运算符
本人是直接从腾讯的软件管家下载的,真香。
新建一个会话框,alt+N新建,alt+o显示已有的连接。下面就是新建会话框的窗口,其中名称由我们自己随意填写,主机就是我们要连接的Linux的ip地址,然后端口号默认即可。
点击确定之后会出现输入用户名和密码,选中记住密码可以在下次直接登陆。
至此就会连接上Linux的主机了。
Apache平台是一个框架,允许使用简单的编程模型。在计算机集群中对大型数据集进行分布式处理。该平台被设计成可以从单个服务器扩展到数千台服务器,每个服务器都提供本地计算。该平台也被设计成可检测和处理应用层的故障(高可靠,高容错)。
这里本人已经在hadoop官网下载好相应的hadoop安装包,但是由于保存在windows硬盘中,不能在Linux中得到。利用wm系统中的共享文件夹的方式来实现挂载以及后续安装。
问题:
安装VmTools用来共享文件夹:
参考:https://www.cnblogs.com/lin3615/p/5602108.html
hgfs的目录下没有文件
参考:https://blog.csdn.net/wear_/article/details/39896775
3.这里出错,
[root@localhost /]# mount -t vmhgfs .host:/share /mnt/hgfs
Error: cannot mount filesystem: No such device
这里看了网上很多的解决办法都没有解决
通过下面来解决,成功实现挂载
[root@localhost /]# vmhgfs-fuse .host:/share /mnt/hgfs/
解压缩:利用tar -zxvf hadoop-3.1.1.tar.gz -C /usr/local/
将文件解压缩到local目录下就好了
添加环境变量:到/etc/profile中进行添加,如图所示
进行环境变量的测试:which hadoop
发现问题:
ERROR: JAVA_HOME is not set and could not be found.
在网络上找了一些资料,但都不能解决我的问题,也都没有说的很明白。这里记录一下。
2.1 java -version检查java是否安装好,如果安装好which java查看java的路径
2.2 进入/usr/local/hadoop/etc/hadoop-env.sh。添加,注意是添加,该文件里面的内容基本都是被注释掉的,我们需要单独添加而不是像网络上说的进行修改就可以的。我这里添加的是export JAVA_HOME=/usr。
!!注意这里的等号两侧不能存在空格。
2.3 source确保修改。
测试hadoop:Hadoop version查看hadoop的版本号,如果没有报错就行了。
下面的例子是计算input目录下所有xml文件中,字符出现的次数
由于Hadoop的集群需要多台服务器,因此尝试对原有的Linux服务器进行克隆得到。在Vmware中右键虚拟机名称,点击管理,然后点击克隆。选择克隆完整克隆,接着选择存储位置即可。
等待一段时间克隆结束,就会多出来新的一个虚拟机。就是我们刚刚取的名字。
我看了下自己克隆出来的虚拟机,发现和老师得到的不一样,因为我克隆的虚拟机的ip和原来的并不一样,因此ip地址不需要修改了。
为了区分两个主机的不一样,分别设置主机名为centos01和centos02。我的Vmware是14.x可能和老师的不一样。vi /etc/sysconfig/network永久性的修改主机名
但是笔者发现,在ifconfig后并没有出现我的ens33网卡。因此应该是网卡的配置出了问题
(vi /etc/udev/rules.d/70-persistent-ipoib.rules 查看网卡信息,网卡的mac地址没有出现问题。
vi /etc/sysconfig/network-scripts/ifcfg-ens33
进入我的网卡配置,发现网卡中的uuid和我之前的uuid相同,前面的肯定已经被占用了,所以这里修改不一样
但是这个时候依然不能找到ens33网卡
解决:
这个时候笔者,点击网络适配器,选择高级,发现每次的mac地址都是不一样的。也就是说克隆出来的虚拟机的mac地址和原来的mac地址是不一样的,这里要进行更换,将上面两个文件中的mac信息进行 更换好了
)
然后我直接用xshell尝试对服务器进行连接。新建一个连接用来连接centos02,发现已经可以连接。
问题:
当一个会话进行中的时候,就无法连接另外一个服务器。不能同时对两个服务器进行连接。但是笔者,再次尝试的时候就突然可以了,难道是因为开始的时候还不稳定??先就这么理解吧,能通就好。
进行两者之间的通信,ping通。
重复以上操作,再次克隆出来一个虚拟机。三个虚拟机用于服务器集群。
相互通信,成功便可以。
主机名称 | IP地址 | 功能 |
---|---|---|
centos01 | 192.168.85.129 | NameNode、DataNode、resourcemanger、nodemanager |
centos02 | 192.168.85.128 | DataNode、nodemanager |
centos03 | 192.168.85.130 | DataNode、nodemanager |
所有机子都需要配置JDK、SSH免登陆(后面说)、Hadoop集群
配置hadoop的相关配置文件
fs.defaultFS
hdfs://centos01:9000
io.file.buffer.size
131072
hadoop.tmp.dir
/home/bigdata/tmp
dfs.replication
3
dfs.block.size
268435456
dfs.namenode.name.dir
/home/hadoopdata/dfs/name
dfs.datanode.data.dir
/home/hadoopdata/dfs/data
dfs.http.address
centos01:50070
dfs.secondary.http.address
centos01:50090
dfs.webhdfs.enabled
false
mapreduce.framework.name
yarn
true
mapreduce.jobhistory.address
centos01:10020
mapreduce.jobhistory.webapp.address
centos01:19888
yarn.resourcemanager.hostname
centos01
yarn.nodemanager.aux-services
mapreduce_shuffle
yarn.resourcemanager.address
centos01:8032
yarn.resourcemanager.scheduler.address
centos01:8030
yarn.resourcemanager.resource-tracker.address
centos01:8031
yarn.resourcemanager.admin.address
centos01:8033
yarn.resourcemanager.webapp.address
centos01:8088
centos01
centos02
centos03
由于在centos01中对hadoop进行了编辑,想要将centos01中的hadoop分发到其他计算机中。
rm -rf /usr/local/had**/
rm -rf ./share/doc/
scp -r ../hadoop**/ centos02:/usr/local/
scp -r ../hadoop**/ centos03:/usr/local/
启动之前在namenode服务器上先格式化,只需要格式化一次就可以
#hadoop namenode -format
启动namenode、datanode、Resourcemanager、NodeManager
全启动:start-all.sh
模块启动:start-dfs.sh start-yarn.sh
单个进程启动:
hadoop-daemon.sh start namenode
hadoop-daemons.sh start datanode
yarn-daemon.sh start namenode
yarn-daemons.sh start datanode
mr-hobhistory-daemon.sh start/stop historyserver
测试:
问题:
笔者在这里和老师一起进行模块格式化。
报错:
ERROR conf.Configuration: error parsing conf hdfs-site.xml
于是乎笔者机内hdfs文件中,将老师给的一些内容进行了删除。这里是比对这hadoop官网的内容,如果官网的配置没有就删除。主要是删除了一些web相关的配置。
之后进行格式化成功进行没有报错。
接着笔者进行
./sbin/start-dfs.sh
报错
Starting namenodes on [centos01]
ERROR: Attempting to operate on hdfs namenode as root
ERROR: but there is no HDFS_NAMENODE_USER defined. Aborting operation.
解决方法参考:https://blog.csdn.net/coffeeandice/article/details/78879151?utm_source=copy
(缺少用户定义而造成的)因此编辑启动和关闭
注意这里不是在start-all里面进行修改,只在start-dfs.sh和stop-dfs.sh中
$ vi sbin/start-dfs.sh
$ vi sbin/stop-dfs.sh
顶部空白处
HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
然后笔者想要和老师一样jps,查看Linux进程,但是发现我这里找不到jps。百度得知jps是java里面的运行程序,这里就回到我之间java路径的定义了。我的Java路径只是一个软路径,真正的路径并没有找到。
参考:https://blog.csdn.net/m290345792/article/details/79073358
最终找到路径:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64/jre/bin/java
但是在这些路径下面并没有出现jps的命令
参考:https://blog.csdn.net/qq_40105363/article/details/80081185
yum install -y java-1.8.0-openjdk-devel
对jdk进行补充安装,安装完后就可以查看了。
这里成功看到我们的datanode、namenode、secondarynamenode启动。
jps查看服务没有报错,接着通过netstat -nltp
查看了出现的ip和端口。发现我们的在hdfs中配置的内容在这里作为服务显示了出来。应该是可以通过web来进行访问的,但是呢在web中却没有成功。在网络上翻了一遍,发现是我的Linux中防火墙开着。关闭防火墙:
#关闭防火墙
systemctl stop firewalld.service
#禁止开机启动
systemctl disable firewalld.service
问题:这里搭建的系统只有一个datanode,没有将三个计算机统一起来。
进入web页面的datanode访问页面,发现第三个服务器没有成功连接上dfs系统。但是单独看centos03的内容发现已经启动了datanode节点,那么问题应该就是出现在centos01和cento03的连接上。进入centos03的hosts配置文件中,发现这里面并没有出现centos01的ip映射,进行添加。
关闭,重新开启dfs文件系统服务。发现依然是这样,这个时候尝试在centos03中ping centos01,发现不能ping同,说名centos03的网络存在问题。直接ping ip地址却发现能ping通,那么就是hosts映射出的问题。对hosts进行修改能够ping通centos01后,重启dfs文件系统。成功。
3、在web网页中点击ulities进入browser界面。在linux中输入。将当前目录下的文件存放到hdfs系统的根目录下面。web中可以显示出来。
hdfs dfs -put ./README.txt /
启动yarn服务
start-yarn.sh
开启服务之后jps发现centos01中多了resourcemanager和nodemanager。而centos02和centos03中则多出来了nodemanager。
web 监控 http://192.168.85.129:8088成功监控
进行wordcount检测。
yarn jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.1.jar wordcount /README.txt /out/00
但是在进行wordcount的时候出现问题。
java.net.NoRouteToHostException: No route to host
经百度发现需要将集群下每一个机子都要关闭防火墙。
都关闭后,再次执行wordcount命令。
Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
Please check whether your etc/hadoop/mapred-site.xml contains the below configuration:
yarn.app.mapreduce.am.env
HADOOP_MAPRED_HOME=${full path of your hadoop distribution directory}
mapreduce.map.env
HADOOP_MAPRED_HOME=${full path of your hadoop distribution directory}
mapreduce.reduce.env
HADOOP_MAPRED_HOME=${full path of your hadoop distribution directory}
经过在网上的查询:
mapreduce.application.classpath
/usr/local/hadoop-3.1.1/share/hadoop/mapreduce/*,
/usr/local/hadoop-3.1.1/share/hadoop/mapreduce/lib/*,
/usr/local/hadoop-3.1.1/share/hadoop/mapreduce/lib-examples/*
这样就能够解决了这个问题了。
但是接下来又出现了内存崩溃的是:
参考:https://www.cnblogs.com/scw2901/p/4331682.html
解决方法:
mapreduce.map.memory.mb
1536
mapreduce.map.java.opts
-Xmx1024M
mapreduce.reduce.memory.mb
3072
mapreduce.reduce.java.opts
-Xmx2560M
注意:此时直接进行ssh centos01还是需要输入密码的。下面的图片就需要密码的输入。
此时.ssh目录下会多出来免密的文件,authorized_key如下
问题:
[root@centos01 .ssh]# ssh centos02
ssh: Could not resolve hostname centos02: Name or service not known
但是直接进行ssh ip地址就是可以的。
这里分析,应该是/etc/hosts下面没有对centos02进行ip和名称的配置。vi hosts将ip centos02加进去,然后出来后发现就能够直接ssh centos02了。
再次通过以上的内容来进行添加密码就可以免密登陆centos02了。
hdfs dfs -
进行查看常用的命令
Usage: hadoop fs [generic options]
[-appendToFile ... ]
[-cat [-ignoreCrc] ...]
[-checksum ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] [-d] [-t ] ... ]
[-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] ... ]
[-count [-q] [-h] [-v] [-t []] [-u] [-x] [-e] ...]
[-cp [-f] [-p | -p[topax]] [-d] ... ]
[-createSnapshot []]
[-deleteSnapshot ]
[-df [-h] [ ...]]
[-du [-s] [-h] [-v] [-x] ...]
[-expunge]
[-find ... ...]
[-get [-f] [-p] [-ignoreCrc] [-crc] ... ]
[-getfacl [-R] ]
[-getfattr [-R] {-n name | -d} [-e en] ]
[-getmerge [-nl] [-skip-empty-file] ]
[-head ]
[-help [cmd ...]]
[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [ ...]]
[-mkdir [-p] ...]
[-moveFromLocal ... ]
[-moveToLocal ]
[-mv ... ]
[-put [-f] [-p] [-l] [-d] ... ]
[-renameSnapshot ]
[-rm [-f] [-r|-R] [-skipTrash] [-safely] ...]
[-rmdir [--ignore-fail-on-non-empty] ...]
[-setfacl [-R] [{-b|-k} {-m|-x } ]|[--set ]]
[-setfattr {-n name [-v value] | -x name} ]
[-setrep [-R] [-w] ...]
[-stat [format] ...]
[-tail [-f] ]
[-test -[defsz] ]
[-text [-ignoreCrc] ...]
[-touchz ...]
[-truncate [-w] ...]
[-usage [cmd ...]]
官网镜像目录:http://maven.apache.org/download.cgi
下载windows中的zip压缩包,下载完成之后直接进行解压即可。
配置环境变量。
配置setting.xml文件,(指定本地仓库位置)。并创建一个本地仓库的空目录。
参考:https://blog.csdn.net/jiruirui213/article/details/78494085
运行命令行mvn help:system完成对本地仓库文件的下载
和java的编辑工具整合(eclipse)
window-preference-搜索maven,然后添加add,directory自己的maven安装目录,finish。继续user setting-global settings选择自己配置的setting文件。
maven报错Missing artifact jdk.tools:jdk.tools:jar:1.8解决方案
参考:https://blog.csdn.net/qy20115549/article/details/53004779
添加tool.jar包到库中就可以了。
然后遇到问题:HADOOP_HOME and hadoop.home.dir are unset.
Could not locate Hadoop executable: D:\hadoop3.1.1\hadoop-3.1.1\bin\winutils.exe
-see https://wiki.apache.org/hadoop/WindowsProblems
然后进入解决方案网站,跳转到github对相应的内容进行下载,之后放到电脑的hadoop/bin目录就ok了。
依然报错:/D:/apache-maven-3.5.4-bin/apache-maven-3.5.4/MavenRepository/org/apache/hadoop/hadoop-core/1.2.1/hadoop-core-1.2.1.jar
我到相应的目录下却发现存在我们需要的jar包。
参考:https://blog.csdn.net/yhao2014/article/details/45578355
网络上说是jar包的冲突所致,需要在build path中删除hadoop-core.xxx.jar。我这里是在pom.xml依赖项里面把相应的dependency去掉。
然后报错和解决办法参考如下:https://www.cnblogs.com/huxinga/p/6868074.html
接着说url不是一个absolute url这里我检查了一下url发现是fs.default写错误。然后进行修改即可。正确代码如下:
package com.tj.hdfs;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.log4j.BasicConfigurator;
/**
* 用java操作hdfs
* */
public class hdfs {
public static void main(String[] args) throws IOException{
BasicConfigurator.configure(); //自动快速地使用缺省Log4j环境。
readFileToConsole("/test.txt");
}
public static void readFileToConsole(String path) throws IOException{
//获取配置
Configuration conf = new Configuration();
//配置
conf.set("fs.defaultFS", "hdfs://192.168.85.129:9000");
//获取hdfs文件系统的操作对象
FileSystem fs = FileSystem.get(conf);
FSDataInputStream fis = fs.open(new Path(path));
IOUtils.copy(fis, System.out);
}
}
输出为test.txt文件的内容
至此成功使用eclipse在windows中读取相应的文件内容。
同理上传和保存本地等操作
public static void readFileToLocal(String path) throws IOException, InterruptedException, URISyntaxException {
//获取配置
Configuration conf = new Configuration();
//配置
// conf.set("fs.defaultFS", "hdfs://192.168.85.129:9000");
//获取hdfs文件系统的操作对象
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.85.129:9000"), conf, "root");
FSDataInputStream fis = fs.open(new Path(path));
OutputStream out = new FileOutputStream(new File("D:\\hadoop3.1.1\\testFromHdfs.txt"));
IOUtils.copy(fis, out);
}
public static void copyFromLocal() throws IOException, InterruptedException, URISyntaxException{
//获取配置
Configuration conf = new Configuration();
//配置
// conf.set("fs.defaultFS", "hdfs://192.168.85.129:9000");
//获取hdfs文件系统的操作对象
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.85.129:9000"), conf, "root");
fs.copyFromLocalFile(new Path("D:\\hadoop3.1.1\\testFromHdfs.txt"), new Path("/test/fromlocal"));
System.out.println("finished");
远程过程调用(RPC)是一个协议,程序可以使用这个协议请求网络中另一台计算机上某程序的服务而不需要知道网络的细节。
必备知识:
网络七层模型
网络四层模型
RPC模式:
C/S模式
基于传输层协议(TCP/IP)
事件处理模型(请求、计算、响应)
RPC设计目的:
调用非本机的方法
不同语言程序之间的通讯
不了解底层通讯,像本地方法一样调用
RPC的作用:
分布式程序的基础(分布式操作系统,分布式计算,分布式软件设计)
垂直应用服务化拆分
RPC的特点:
封装网络交互
远程调用对象的代理
支持容器(Spring、Jetty等)
可配置、可扩展
是什么:
分布式服务的协调服务
能做什么:
管理分布式服务
通过分布式服务的一致性、对分布式服务做协调
强一致性
zookeeper架构:
zk集群一般需要奇数台服务器,当n/2台zk服务ok,则整个zk集群可用。
leader:老大,管理小弟。然后负责来自client的数据读写请求,先把数据写到内存,然后持久化到本地,然后通知followers及时同步
follower:小弟,负责数据的同步,还会参与选举等
所有的leader和follower都称为server。
快速选举机制:当leader挂掉之后,快速从其余的follower中选举出一个leader
原子广播协议(保证数据一致性):leader广播所有follower同步数据
zookeeper的数据模型:
类似文件系统的一个树形结构,用于携带少量数据。
每一个数据节点(树中的每一个分支节点或者叶子节点)称之为znode,每一个节点与传统树形文件系统的区别。
目标:传统文件系统设计用于大量数据,而zk用于存储少量数据来进行协调服务,每一个znode节点既是目录又是文件。
znode节点有四种:
普通znode:
普通序列化znode: /name000001
临时znode:当session退出或者失效,则该节点消失
临时序列化znode:
watcher:事件(节点可以注册事件)节点、更新节点、创建子节点。(事件具有一致性)
下载网址:http://mirror.bit.edu.cn/apache/zookeeper/stable/
解压安装:tar -zxvf XXX。这里笔者解压到/usr/local/目录下面。删除docs文件,方便后续移动
配置环境变量:vi /etc/profile。修改完成source
修改 ./conf/zoosample.cfg名称和内容
mv ./conf/zoo_sample.cfg ./conf/zoo.cfg
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/zkdata/
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
#2888为通信端口,3888为选举端口
server.1=centos01:2888:3888
server.2=centos02:2888:3888
server.3=centos03:2888:3888
scp -r ../zookerxxx centos02:/usr/local
。并分别配置相应的环境变量随便敲,进入shell提示界面
ls查看节点
create -e 创建临时节点,-s为序列节点。
set为修改节点内容。
get查看节点内容
rmr递归删除,delete删除单节点
在server.1中创建一个文件,可以在server.2中直接检查到该文件。强一致性。
每一个namenode的上面都有一个zookeeper fail转移控制。在hadoop2.x中通常由两个namenode组成,一个处于activity状态,一个处于standby状态。Active NameNode对外提供服务,而Standby NameNode则不对外提供服务,仅同步active namenode的状态,以便能够在它失败的时候快速进行切换。
hadoop2.0官方提供两种HDFS HA的解决方案,一种是NFS,另一种是QJM(由cloudra JournalNode提出。类似于zookeeper)。这里使用QJM完成。主备NameNode之间通过一组JournalNode同步元数据信息,一条数据只要成功写入多数JournalNode即认为写入成功。通常配置奇数个journalNode。
机器规划:
centos01 namenode datanode journalnode QuroumPeerMain zkfc
cnetos02 namenode datanode journalnode QuroumPeerMain zkfc
centos03 datanode journalnode QuroumPeerMain zkfc
免登陆:
两个老大之间,老大对小弟的免登陆
配置:普通集群进行备份,三台机器
mv /usr/local/hadoop-3.1.1/ /usr/local/hadoop-3.1.1_backup
再次解压安装hadoop
打开notepad,选中插件-NppFTP-showNppFTPWindow。 没有该选项的到网络上进行下载,然后将nppftp.dll放置到notepad安装目录下的plugin目录下,再次启动notepad就有了。
选择设置中,profile那一项进行如下设置。主机名端口都要和自己的对应上去。
!!注意:这里的连接方式是SFTP,并非默认方式。
此时便可以通过notepad来直接对Linux中的文件进行 操作了。
fs.defaultFS
hdfs://tj
hadoop.tmp.dir
/home/hahadoopdata/tmp
io.file.buffer.size
4096
dfs.nameservices
tj
dfs.ha.namenodes.tj
nn1,nn2
dfs.namenode.rpc-address.tj.nn1
centos01:8020
dfs.namenode.rpc-address.tj.nn2
centos02:8020
dfs.namenode.http-address.tj.nn1
centos01:9870
dfs.namenode.http-address.tj.nn2
centos02:9870
dfs.namenode.shared.edits.dir
qjournal://centos01:8485;centos02:8485;centos03:8485/tj
dfs.journalnode.edits.dir
/home/hahadoopdata/journal/data
dfs.client.failover.proxy.provider.mycluster
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
dfs.ha.fencing.methods
sshfence
dfs.ha.fencing.ssh.private-key-files
/home/root/.ssh/id_rsa
dfs.ha.fencing.ssh.connect-timeout
30000
dfs.ha.automatic-failover.enabled
true
ha.zookeeper.quorum
centos01:2181,centos02:2181,centos03:2181
centos01
centos02
centos03
scp -r ../hadoop-3.1.1 centos02:/usr/local/
免登陆配置,centos01和centos02对外免登陆
启动zk
启动journalnode服务
单个启动 ./sbin/hadoop-daemon.sh start journalnode
多个启动 ./sbin/hadoop-daemons.sh start journalnode
挑选两个namenode之中的一台来格式化,
hdfs namenode -format
格式化的时候存在问题
观察可以发现我们在hdfs.xml中配置的好几个都在,但是namenode的name文件夹却没有格式化出来。
报错:
2018-10-07 22:24:45,804 INFO ipc.Client: Retrying connect to server: centos03/192.168.35.130:8485. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2018-10-07 22:24:45,805 INFO ipc.Client: Retrying connect to server: centos02/192.168.35.129:8485. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
解决:参考
https://blog.csdn.net/u014729236/article/details/44944773/
解决方法:先用./zkServer.sh start 启动各个zookeeper,再用./ hadoop-daemon.sh start journalnode启动各个NodeName上的 JournalNode进程,确保所有都启动。然后再进行格式化即可。
然后启动centos01中启动namenode。 hadoop-daemons.sh start namenode
这句代码是老师给的,但是在我这里报错。并且提醒 hdfs --daemon start namenode
我这里使用这句话成功启动。
在另外一台namenode机子上拉元数据(也可以是复制)hdfs namenode -bootstrapStandby
。拉取完毕后在centos02的时候也有dfs/name文件
启动start-all.sh
分别在start-dfs.sh,start-yarn.sh;stop-dfs.sh,stop-yarn.sh中添加相应内容。
继续百度:https://blog.csdn.net/xjping0794/article/details/78552922
这里说hdfs-site.xml文件缺少配置,加上就可以了。修改后记得分发到另外两个主机中。
dfs.client.failover.proxy.provider.testcluster
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
添加内容
hdfs dfs -put /usr/local/hadoop-3.1.1/etc/hadoop/workers /
成功添加。
解决:这里是通信的问题,下面的配置采用的是ssh的通信,我们需要找到.ssh文件下面,笔者一开始没有对应正确,由于笔者一直是root用户登陆,因此文件应该保存在/root/目录下面。
dfs.ha.fencing.ssh.private-key-files
/root/.ssh/id_rsa
这里成功实现自动切换。
方案:
首先,分别统计每个文件中单词出现的次数 map()
然后,累加不同文件中同一个单词出现的次数; reduce()
wordcount示例运行
在dfs中创建input目录 hadoop fs -mkdir /data/input
将conf中的文件拷贝到dfs的input中 hadoop fs -put conf/* /data/input
/
运行wordcount hadoop jar hadoop-example…jar wordcount /data/input /data/output
编写MapReduce程序
实现wordcount程序编写:使用eclipse编写mapreduce程序,打包成jar,上传到集群中,使用hadoop jar命令运行。使用MapReduce eclipse插件程序开发并运行Job
未解决
2. 这里笔者想要重新建立一个maven project,但是新建的工程依赖的Maven库文件并全面。为此我不得不在已经有的project中添加package。
3. java代码
package MapReduce;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class wordcount {
/*
* input
*
* words
* hello tj hello world
* hi tj hi world
* best hadoop
*
* map阶段
* KEYIN行偏移量:每一行的第一个字母距离该文件首位置的距离(Map阶段输入key的类型)0
* VALUEIN行的值:(Map阶段输入value类型)
* KEYOUT:(Map阶段输出Key的类型)
* VALUEOUT:(Map阶段输出key类型)
*
* map阶段输入:每一行调用一次map方法
* 0 hello tj hello world
* 20 hi tj hi world
* 36 best hadoop
*
* map阶段输出:
* best 1
* hadoop 1
* hello 1
* hello 1
* hi 1
* hi 1
* tj 1
* tj 1
* world 1
* world 1
*
*
* reduce阶段输入:
* reduce的输入类型必须和map阶段的输出类型key、value类型相同
* best list<1>
* hadoop list<1>
* hello list<1, 1>
* hi list<1, 1>
* tj list<1, 1>
* world list<1, 1>
*
* reduce阶段输出:
* best 1
* hadoop 1
* hello 2
* hi 2
* tj 2
* world 2
* */
public static class MyMapper extends Mapper{
public Text K = new Text();
public IntWritable V = new IntWritable();
@Override
protected void map(LongWritable key, Text value,Context context)
throws IOException, InterruptedException {
//1. 从输入数据中获取每一个文件中每一行的值
String line = value.toString();
//2. 每一行数据进行切分
String []words = line.split(" ");
//3. 循环处理
for(String word:words) {
K.set(word);
V.set(1);
context.write(K, V);
}
}
}
public static class MyReduce extends Reducer{
@Override
protected void reduce(Text arg0, Iterable arg1,
Reducer.Context arg2) throws IOException, InterruptedException {
int count = 0;
for(IntWritable i:arg1) {
count += i.get();
}
arg2.write(arg0, new IntWritable(count));
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1. 获取配置对象信息
Configuration configuration = new Configuration();
//2. 对conf进行设置(没有就不用)、
//3. 获取Job对象
Job job = Job.getInstance(configuration, "mywordcount");
//4. 设置job的运行主类
job.setJarByClass(wordcount.class);
//5. 对map阶段进行设置
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
//6. reduce阶段进行设置
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//7. 提交job作业
int isOK = job.waitForCompletion(true)?0:1;
//8. 退出job
System.exit(isOK);
}
}
导出为jar包,左侧选中相应package,右键-export-java-JAR file。将这个jar包放进linux系统中,进行wordcount运行。
MapReduce为包名,wordcount为类名
yarn jar ./wordcount.jar MapReduce.wordcount /testInput /out/07
问题ConfiguredRMFailoverProxyProvider: Failing over to rm1
原因:没有启动yarn框架的resourceManager。
package MapReduce;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/*
* 汽车流水线的三个事件段的记录算一个平均值
*
* l_1 393 430 276
* l_2 388 560 333
* l_3 450 600 312
*
* */
public class AvgDemo {
public static class MyMapper extends Mapper{
public Text K = new Text();
public FloatWritable V = new FloatWritable();
@Override
protected void map(LongWritable key, Text value,Context context)
throws IOException, InterruptedException {
//1. 从输入数据中获取每一个文件中每一行的值
String line = value.toString();
//2. 每一行数据进行切分
String []words = line.split("\t");
//3. 业务处理
String linename = words[0];
float z = Float.parseFloat(words[1]);
float w = Float.parseFloat(words[2]);
float y = Float.parseFloat(words[3]);
K.set(linename);
V.set((z+w+y/(words.length - 1)));
context.write(K, V);
}
}
public static class MyReduce extends Reducer{
@Override
protected void setup(Context context)
throws IOException, InterruptedException {
context.write(new Text("生产线\t生产平均值"), new FloatWritable());
}
@Override
protected void reduce(Text arg0, Iterable arg1,
Reducer.Context arg2) throws IOException, InterruptedException {
arg2.write(arg0, new FloatWritable(arg1.iterator().next().get()));
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1. 获取配置对象信息
Configuration configuration = new Configuration();
//2. 对conf进行设置(没有就不用)、
//3. 获取Job对象
Job job = Job.getInstance(configuration, "myAvg");
//4. 设置job的运行主类
job.setJarByClass(wordcount.class);
//5. 对map阶段进行设置
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(FloatWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
//6. reduce阶段进行设置
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(FloatWritable.class);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//7. 提交job作业
int isOK = job.waitForCompletion(true)?0:1;
//8. 退出j
System.exit(isOK);
}
}
数据源 | awk -F " " ‘BEGIN{} {} {} …END{}’
实例
对passwd文件中第3个数据大于等于500的时候,进行输出
cat /etc/passwd | awk -F ':' 'BEGIN{print "名字\t用户ID"} {if($3>=500) print $1, $3}'
意思:洗牌或者弄乱
collections.shuffle(list):随机打乱参数list里的元素顺序
MapReduce里的shuffle:描述着数据从map task输出到reduce task输入的这段过程
分片:block的一个逻辑组织。注意:10%的冗余,空文件也会做成一个分片,不可切割的文件会为一个片。
inputSplit的默认实现FileSplit。fileSplit将会被进行RecordReader。
分区:决定map阶段的输出交由哪一方reduce处理。分散map阶段输出的处理数据,将输出多个结果集。
自定义分区
分区:Partitioner
输入数据
Hello Hi Hi
hi hello
163.com
qq.com
189.com
@163.com
@qq.com
*123.com
输出:
首字母为A-Z,a-z,0-9,其他分别放在不同的文件中
class partitionDemo:
package MapReduce;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/*
* 分区:Partitioner
输入数据
Hello Hi Hi
hi hello
163.com
qq.com
189.com
@163.com
@qq.com
*123.com
输出:
首字母为A-Z,a-z,0-9,其他分别放在不同的文件中
结果文件:part-r-00000
Hello 2
Hi 2
结果文件:part-r-00001
hello 1
hi 1
qq.com 1
结果文件:part-r-00002
163.com 1
189.com 1
结果文件:part-r-00003
@163.com 1
@qq.com 1
*123.com 1
* */
public class PartitionDemo {
public static class MyMapper extends Mapper{
@Override
protected void map(LongWritable key, Text value, Mapper.Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split(" ");
for(String s:words) {
context.write(new Text(s), new Text(1+""));
}
}
}
public static class MyReduce extends Reducer{
@Override
protected void reduce(Text arg0, Iterable arg1, Reducer.Context arg2)
throws IOException, InterruptedException {
int count = 0;
for(Text num: arg1) {
count += Integer.parseInt(num.toString());
}
arg2.write(arg0, new LongWritable(count));
}
}
public static void setConf(Configuration conf) {
//对conf属性进行设置
conf.set("fs.defaultFS", "hdfs://tj");
conf.set("dfs.nameservices", "tj");
conf.set("dfs.ha.namenodes.tj", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.tj.nn1", "centos01:8020");
conf.set("dfs.namenode.rpc-address.tj.nn2", "centos02:8020");
conf.set("dfs.client.failover.proxy.provider.mycluster", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
}
public static Configuration getConf() {
return new Configuration();
}
public static int main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration configuration = getConf();
setConf(configuration);
Job job = Job.getInstance(configuration, "job");
//4. 设置job的运行主类
job.setJarByClass(PartitionDemo.class);
//5. 对map阶段进行设置
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
//添加分区信息
job.setPartitionerClass(MyPartioriner.class);
//设置分区数目,一个reduce对应一个分区
job.setNumReduceTasks(4);
FileInputFormat.addInputPath(job, new Path(args[0]));
//6. reduce阶段进行设置
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//7. 提交job作业
int isOK = job.waitForCompletion(true)?0:1;
//8. 退出j
System.exit(isOK);
return 0;
}
}
class MyPartitioner
package MapReduce;
import org.apache.hadoop.hdfs.util.StripedBlockUtil.StripeRange;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
import com.sun.tools.javac.util.Context.Key;
/*
* 自定以的partitioner
* */
public class MyPartioriner extends Partitioner{
@Override
public int getPartition(Text arg0, Text arg1, int arg2) {
// TODO Auto-generated method stub
String firstChar = arg0.toString().substring(0, 1);
if(firstChar.matches("^[A-Z]")) {
return 0%arg2;
}else if(firstChar.matches("^[a-z]")) {
return 1%arg2;
}else if(firstChar.matches("^[0-9]")) {
return 2%arg2;
}else {
return 3%arg2;
}
}
}
class daopaisuoying
package MapReduce;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/*
* 倒排索引
*
* 输入数据:
* 1.html:
* hadoop hadoop hadoop is good
* 2.html:
* hadoop hbase hbase is nice
* 3.html:
* hadoop hadoop hbase spark spark spark is better
*
* 输出:
* better 3.html:1
* good 1.html:1
* hadoop 1.html:3;2.html:1;3.html:2
* hbase 2.html:2;3.html:1
* is 1.html:1;2.html:1;3.html:1
* nice 2.html:1
* spark 3.html:3
*
* */
public class daoPaiSuoYing {
public static class MyMapper extends Mapper{
@Override
protected void map(LongWritable key, Text value, Mapper.Context context)
throws IOException, InterruptedException {
//获取文件的名称
InputSplit iSplit = context.getInputSplit();
String name =((FileSplit)iSplit).getPath().getName();
String line = value.toString();
String[] words = line.split(" ");
for(String s:words) {
context.write(new Text(s+"_"+name), new Text(1+""));
}
}
/*
* 输出:
* hadoop_1.html 1
* ...
* */
}
public static class MyReduce extends Reducer{
@Override
protected void reduce(Text arg0, Iterable arg1, Reducer.Context arg2)
throws IOException, InterruptedException {
/*
* hadoop<1.html:3,2.html:1,3.tml:2>
* ...
* */
String string="";
for(Text num:arg1) {
string += num.toString()+";";
}
arg2.write(arg0, new Text(string.substring(0, string.length()- 1)));
}
}
public static void setConf(Configuration conf) {
//对conf属性进行设置
conf.set("fs.defaultFS", "hdfs://tj");
conf.set("dfs.nameservices", "tj");
conf.set("dfs.ha.namenodes.tj", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.tj.nn1", "centos01:8020");
conf.set("dfs.namenode.rpc-address.tj.nn2", "centos02:8020");
conf.set("dfs.client.failover.proxy.provider.mycluster", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
}
public static Configuration getConf() {
return new Configuration();
}
public static int main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration configuration = getConf();
setConf(configuration);
Job job = Job.getInstance(configuration, "job");
//4. 设置job的运行主类
job.setJarByClass(daoPaiSuoYing.class);
//设置combiner
job.setCombinerClass(MYCombiner.class);
//5. 对map阶段进行设置
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
//6. reduce阶段进行设置
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
return job.waitForCompletion(true)?0:1;
}
}
class myConbiner
package MapReduce;
import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class MYCombiner extends Reducer{
@Override
protected void reduce(Text arg0, Iterable arg1, Reducer.Context arg2)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
/**
* 输入:
* hadoop_1.html 1
* ...
* */
String str[] = arg0.toString().split("_");
int count = 0;
for(Text num:arg1) {
count = Integer.parseInt(num.toString());
}
arg2.write(new Text(str[0]), new Text(str[1] + ":"+count));
}
}
运行
yarn jar /home/wordcount.jar MapReduce.daoPaiSuoYing /di /out/16
结果
package MapReduce;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;
/*
* 1. 自定义数据类型需要实现writable(不能排序),或者writableComparable(可排序)
* 2. 实现该接口的相应方法write,readFields,compareTo
* 3. write,readFields里面的字段个数和顺序要一致,类型需要匹配
* 4. 可以重写toString,equal,等方法
* */
public class TopNWritable implements WritableComparable{
public String word;
public int count;
public TopNWritable() {}
public TopNWritable(String word, int count) {
super();
this.word = word;
this.count = count;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
//反序列化
public void readFields(DataInput arg0) throws IOException {
// TODO Auto-generated method stub
this.word = arg0.readUTF();
this.count = arg0.readInt();
}
//序列化
public void write(DataOutput arg0) throws IOException {
// TODO Auto-generated method stub
arg0.writeUTF(this.word);
arg0.writeInt(this.count);
}
public int compareTo(TopNWritable o) {
// TODO Auto-generated method stub
return o.count - this.count;
}
//格式化输出
@Override
public String toString() {
return "[" + word + "\t"+ count + "]";
}
}
package MapReduce;
import java.io.IOException;
import java.util.TreeSet;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/*
* 倒排索引
*
* 输入数据:
* 1.html:
* hadoop hadoop hadoop is good
* 2.html:
* hadoop hbase hbase is nice
* 3.html:
* hadoop hadoop hbase spark spark spark is better
*
* 输出:
* better 3.html:1
* good 1.html:1
* hadoop 1.html:3;2.html:1;3.html:2
* hbase 2.html:2;3.html:1
* is 1.html:1;2.html:1;3.html:1
* nice 2.html:1
* spark 3.html:3
*
* */
public class TopNDemo {
public static class MyMapper extends Mapper{
@Override
protected void map(LongWritable key, Text value, Mapper.Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split(" ");
for(String s:words) {
context.write(new Text(s), new Text(1+""));
}
}
}
public static class MyReduce extends Reducer{
//定义一个存储最终输出的容器
public static final int Top_N = 3;
@Override
protected void cleanup(Reducer.Context context)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
//循环打印ts中的元素
for(TopNWritable topNWritable:ts) {
context.write(topNWritable, NullWritable.get());
}
}
TreeSet ts=new TreeSet();
@Override
protected void reduce(Text arg0, Iterable arg1, Reducer.Context arg2)
throws IOException, InterruptedException {
int count = 0;
for(Text t:arg1) {
count += Integer.parseInt(t.toString());
}
//构造最终的输出类型
TopNWritable tNWritable = new TopNWritable(arg0.toString(), count);
//将tn对象添加到ts中
ts.add(tNWritable);
//如果ts里面的数据大于Top_N的时候将移除最后一个
if(ts.size()>Top_N) {
ts.remove(ts.last());
}
//可能存在多个文件,每一个文件不能只输出一次,需要将所有的reduce结束后来进行输出
}
}
public static void setConf(Configuration conf) {
//对conf属性进行设置
conf.set("fs.defaultFS", "hdfs://tj");
conf.set("dfs.nameservices", "tj");
conf.set("dfs.ha.namenodes.tj", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.tj.nn1", "centos01:8020");
conf.set("dfs.namenode.rpc-address.tj.nn2", "centos02:8020");
conf.set("dfs.client.failover.proxy.provider.mycluster", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
}
public static Configuration getConf() {
return new Configuration();
}
public static int main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration configuration = getConf();
setConf(configuration);
Job job = Job.getInstance(configuration, "job");
//4. 设置job的运行主类
job.setJarByClass(TopNDemo.class);
//5. 对map阶段进行设置
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
//6. reduce阶段进行设置
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(TopNWritable.class);
job.setOutputValueClass(NullWritable.class);
FileOutputFormat.setOutputPath(job, new Path(args[1]));
return job.waitForCompletion(true)?0:1;
}
}
运行结果
至此,对于hadoop框架以及后面的关于hive方面的知识暂时不进行学习,因为目前还不是很用的上这方面的知识。这里大概回顾一下hadoop的内容把。首先就是linux方面的内容,在hadoop的学习中对于linux的简单操作和系统有了初步的了解和入门。其次就是hdfs,hadoop中的分布式文件系统的搭建,然后就是yarn内容以及wordcount的计算方面知识,接着就是高可用ha方面。通过在windows中利用maven来对hdfs文件系统中的内容进行访问,已经通过java编写类似于wordcount这类的程序,对于hadoop的简单应用有了一定的了解。
暂时暂停关于hadoop课程的学习,后续如果继续接触和hadoop相关的内容,我会继续在这里进行更新。