吃水不忘挖井人,我看的课是这个,课程带着安装,搞虚拟机,很详细,推荐一波
Hadoop102:
cd / 表示的是返回/
cd ~ 表示的是返回/home/fools
$HADOOP_HOME 配置的位置为/opt/module/hadoop-3.1.3
如果某个集群namenode或datanode等出现异常,这时候只要先停掉每个集群sbin/stop-xxxxx.sh
,删除每个服务器的data,logs目录rm -rf data/ logs/
,然后再初始化hdfs namenode -format
,就可以复原了
/opt/module/hadoop-3.1.3/data/dfs/data/current/BP-1116405649-192.168.10.102-1632297070587/current/finalized/subdir0/subdir0
大数据主要解决海量数据的采集,存储,分析计算问题。
hadoop四大优势:
hadoop distributed file system,分布式文件系统
NameNode:管理数据存储在什么位置;存储文件的元数据:文件名,文件目录结构,文件属性,以及每个文件所在的块列表和DataNode
DataNode:具体存储文件块数据,以及块数据的校验和
yet another resource negotiator,是一种资源协调者,是hadoop的资源管理器
将任务交给很多人去做,然后将结果一起汇总在服务器
分布式文件管理系统,适合一次写入,多次读出(可以追加)
优点
高容错性:数据保存为多个副本,一个丢失后可以快速恢复
适合处理大数据:可以处理文件规模很大,文件数量很多的文件
可以构建在廉价机器上
缺点
不适合低延时访问
无法高效搜索小文件
不支持并发写入
不支持文件随机修改,只支持追加
所有HDFS的原数据名称都在这里存储
副本的配置策略
管理映射信息(哪一块数据存储在哪一块DataNode)
处理客户读写请求
存储实际的数据块
执行数据块的读写
文件切分:上传HDFS之前,client会按照NameNode的块大小的要求(一般是128MB)进行切分,然后再上传
与NameNode交互,获取位置信息
与DataNode交互,获取或写入数据
提供一些命令来管理,访问HDFS
HDFS文件块大小普遍为128M,256M,这主要是和磁盘的传输速率有关,因为寻址时间为传输时间的1%是最佳状态。
如果块太大,寻址很快,传输较慢
如果块太小,寻址很慢,传输很快
其实hdfs的shell操作就是普通的shell操作前面加上hadoop fs -
,后面的内容和linux中差别不大
在使用xshell之前需要开启hadoop集群
`myhadoop.sh start`
or
`sbin/start-dfs.sh`
`sbin/start-yarn.sh`
举例:
想查看help:hadoop fs -help rm
创建文件:hadoop fs -mkdir /sanguo
上传
下载
另外还有其他的正常操作:
-ls
-cat
-cp
-mv
-tail
-rm
其实万变不离其宗:
获取文件系统----创建目录----关闭资源
fs = FileSystem.get(uri,configuration,user);
fs.mkdirs(new Path("/xiyou/huaguoshan1"));
fs.close()
我们需要的操作只是获取文件系统的内容要写清楚,函数的参数传递清楚,关闭资源
package com.atguigu.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
// 正常的流程:获取文件系统----创建目录----关闭资源
public class HDFSclient {
private FileSystem fs;
@Before
public void init() throws URISyntaxException, IOException, InterruptedException {
// 链接的集群地址
URI uri = new URI("hdfs://hadoop102:8020");
// 创建一个配置文件
Configuration configuration = new Configuration();
// 用户
String user = "fools";
//获取用户客户端对象
fs = FileSystem.get(uri,configuration,user);
}
@After
public void close() throws IOException {
// 关闭资源
fs.close();
}
@Test
public void testmkdir() throws URISyntaxException, IOException, InterruptedException {
// 创建一个文件夹
fs.mkdirs(new Path("/xiyou/huaguoshan1"));
}
@Test
public void testPut() throws IOException {
fs.copyFromLocalFile(false,false,
new Path("C:\\Xshell7/sunwukong.txt"),new Path("hdfs://hadoop102/xiyou/huaguoshan"));
}
// 优先级:hdfs-default.xml-->hdfs-site.xml-->项目资源目录下resource配置-->代码里面配置
@Test
public void testDownload() throws IOException {
fs.copyToLocalFile(false,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("D:\\sunhouzi.txt"));
}
@Test
public void testRename() throws IOException {
fs.rename(new Path("/wcinput/word.txt"),new Path("/wcinput/cc.txt"));
}
@Test
public void testMv() throws IOException {
fs.rename(new Path("/wcinput/cc.txt"),new Path("/tmp/sss.txt"));
}
@Test
public void testRenameRoot() throws IOException {
fs.rename(new Path("/wcinput"),new Path("/input"));
}
@Test
public void testGetInfo() throws IOException {
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while (listFiles.hasNext()) {
LocatedFileStatus fileStatus = listFiles.next();
System.out.println(Arrays.toString(fileStatus.getBlockLocations()));
System.out.println(fileStatus.getLen());
}
}
@Test
public void isContent() throws IOException {
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for(FileStatus status:listStatus){
if(status.isFile()){
System.out.println("文件"+status.getPath().getName());
}else{
System.out.println("非文件"+status.getPath().getName());
}
}
}
}
网络拓扑节点距离计算:
而副本选择方面,首先第一个是本地的节点,第二个是附近机架的一个节点,第三个是第二个所在的机架的另一个节点,
客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
2NN主要用于辅助NN中FsImage和Edits的合并
FsImage文件是HDFS系统元数据的永久检查点,包含HDFS文件系统所有目录和文件inode的序列化信息
Edits文件存放所有更新操作,所有写操作执行时都会被首先记录在这里
内存:FsImage存储数据,Edits存储追加信息
开机的时候FsImage和Edits加载到内存中;关机的时候,将Edits追加到FsImage中;
但是这时候Edits很多可能导致速度慢,需要2NN帮助在开机的时间里合并
第一阶段:NameNode启动
第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
客户端对元数据进行增删改的请求。
NameNode记录操作日志,更新滚动日志。
NameNode在内存中对元数据进行增删改。
第二阶段:Secondary NameNode工作
Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
Secondary NameNode请求执行CheckPoint。
NameNode滚动正在写的Edits日志。
将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
生成新的镜像文件fsimage.chkpoint。
拷贝fsimage.chkpoint到NameNode。
NameNode将fsimage.chkpoint重新命名成fsimage。
可以通过oiv
oev
来查看fsimage文件和edits文件
2NN的checkpoint时间设置以及内存多大进行checkpoint的设置在hdfs-default.xml中
DataNode每6小时向NameNode上报所有块信息
DataNode每3秒返回心跳信息,如果10分钟30秒没有收到心跳信息,就认为当前dataNode挂掉,不再向此dataNode传入或查找信息
DataNode的数据完整性一般使用CRC32进行校验
掉线的时限设置一般也是在hdfs-site.xml中
分布式运算程序的编程框架,mapreduce将用户编写的代码和自带默认组件整合成一个完整的分布式运算程序
分布式运算程序一般分为MapTask阶段,ReduceTask阶段,一个模型只能包含一个map阶段和一个reduce阶段,如果业务很复杂也只能穿行运行
一般包括三个实例进程:MrAppMaster,MapTask,ReduceTask
MrAppMaster:负责整个程序的过程调度和状态协调
MapTask:负责Map阶段数据处理流程
ReduceTask:负责Reduce阶段数据处理流程
一般程序分为Mapper,Reducer,Driver
mapper:
输入的KV对K为当前的偏移量(位置),V为偏移量对应的字符串
package com.atguigu.mapreduce.wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
Text k = new Text();
IntWritable v = new IntWritable(1);
@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);
context.write(k, v);
}
}
}
reducer:
package com.atguigu.mapreduce.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 WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
int sum;
IntWritable v = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
// 1 累加求和
sum = 0;
for (IntWritable count : values) {
sum += count.get();
}
// 2 输出
v.set(sum);
context.write(key,v);
}
}
driver:
相当于Yarn集群的客户端,用于提交整个程序到Yarn集群
序列化:把内存中的对象,转换成字节序列,存储在磁盘,以便于存储和网络传输
反序列化:将收到的字节序列或者是磁盘的持久化数据转换为内存的对象
hadoop的序列化相对于java的来说,校验信息更少,在网络中传输更加方便。
mapper的输出(reducer的输入)如果是多个值的bean对象,我们就需要自己序列化
实际实现需要新建类FlowBean继承自Writable接口,
切片与mapTask并行度
**数据块:**Block是HDFS物理上把数据分成一块一块。数据块是HDFS存储数据单位。
框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。
(1)虚拟存储过程:
将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。
例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。
(2)切片过程:
(a)判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。
(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
(c)测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:
1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)
最终会形成3个切片,大小分别为:
(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M
shuffle是map方法之后,reduce方法之前的数据处理过程
partition分区是指在map结束之后,将统计结果按照条件输出到不同的文件中
默认partition按照key的hashcode对reduceTask的个数去摸得到的
我们可以自定义分区,但是需要在driver类中设置好job.set
,否则不会生效
需要注意的是:
MapTask和ReduceTask都会对key进行排序,属于hadoop的默认行为
map阶段的排序:
mapTask的处理结果暂时放在环形缓冲区
环形缓冲区使用了80%之后,开始反向写(提高效率),对缓冲区中的数据进行快速排序,(这里可以加入combiner功能)并将结果写出在磁盘上
当所有数据处理完毕后,对磁盘的所有文件进行归并排序(归并排序之后可以再做一次combiner)
reduceTask阶段的排序
reduce会自己拉取mapTask的数据文件到自己的内存中,当文件太大,会存在磁盘中
所有数据拷贝完成后,ReduceTask统一对内存和磁盘上的所有数据进行一次归并排序
如果key是一个bean对象?
实现bean对象需要重写writable接口,为了让bean对象作为key可以排序,需要实现WriteableComparable接口重写compareTo方法
combiner属于mapper和reducer之外,combiner组件的父类是reducer
combiner的意义在于对MapTask输出进行局部汇总,减少网络传输量
combiner不能影响业务逻辑(不能提前求平均)
如果没有reducer阶段,则combiner不存在
自定义Combiner实现步骤(一般来说直接set reducer.class就可以实现,不需要手动写)
(a)自定义一个Combiner继承Reducer,重写Reduce方法
public class WordCountCombiner extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable outV = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable value : values) {
sum += value.get();
}
outV.set(sum);
context.write(key,outV);
}
}
(b)在Job驱动类中设置:
job.setCombinerClass(WordCountCombiner.class);
hadoop如果向输出数据到MySQL,HBASE等等,需要自己定义一 个类继承FileOutputFormat,改写RecordWriter
(1)Read阶段:MapTask通过InputFormat获得的RecordReader,从输入InputSplit中解析出一个个key/value。
(2)Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。
(3)Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
(4)Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作。
溢写阶段详情:
步骤1:利用快速排序算法对缓存区内的数据进行排序,排序方式是,先按照分区编号Partition进行排序,然后按照key进行排序。这样,经过排序后,数据以分区为单位聚集在一起,且同一分区内所有数据按照key有序。
步骤2:按照分区编号由小到大依次将每个分区中的数据写入任务工作目录下的临时文件output/spillN.out(N表示当前溢写次数)中。如果用户设置了Combiner,则写入文件之前,对每个分区中的数据进行一次聚集操作。
步骤3:将分区数据的元信息写到内存索引数据结构SpillRecord中,其中每个分区的元信息包括在临时文件中的偏移量、压缩前数据大小和压缩后数据大小。如果当前内存索引大小超过1MB,则将内存索引写到文件output/spillN.out.index中。
(5)Merge阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。
当所有数据处理完后,MapTask会将所有临时文件合并成一个大文件,并保存到文件output/file.out中,同时生成相应的索引文件output/file.out.index。
在进行文件合并过程中,MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式。每轮合并mapreduce.task.io.sort.factor(默认10)个文件,并将产生的文件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。
让每个MapTask最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销。
(1)Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。
(2)Sort阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。
(3)Reduce阶段:reduce()函数将计算结果写到HDFS上。
手动设置:job.setNumReduceTasks(4)
我们可以选择在map端或者reduce端进行join
reduce join:
首先需要将两个不同的表放到一个bean中,作为map阶段的输出(针对不同的文件进行不同的处理),并且增加一个flag标签,方便reduce阶段的判断
然后在reduce阶段进行判断,根据不同的flag标签进行不同的操作
reduce阶段的join在reduce阶段处理压力很大,map阶段负载低,资源利用率不高,容易产生数据倾斜
map阶段join
在map阶段的setup中循环读取文件,将一个表的内容缓存在hashmap中,在map阶段进行两个表的匹配,拼接
hadoop的数据清洗仅仅需要mapper程序就可以,符合要求就输出,不符合就直接reture
所以我们需要job.setNumReduceTask(0)
1)输入数据接口:InputFormat
(1)默认使用的实现类是:TextInputFormat
(2)TextInputFormat的功能逻辑是:一次读一行文本,然后将该行的起始偏移量作为key,行内容作为value返回。
(3)CombineTextInputFormat可以把多个小文件合并成一个切片处理,提高处理效率。
2)逻辑处理接口:Mapper
用户根据业务需求实现其中三个方法:map() setup() cleanup ()
3)Partitioner分区
(1)有默认实现 HashPartitioner,逻辑是根据key的哈希值和numReduces来返回一个分区号;key.hashCode()&Integer.MAXVALUE % numReduces
(2)如果业务上有特别的需求,可以自定义分区。
4)Comparable排序
(1)当我们用自定义的对象作为key来输出时,就必须要实现WritableComparable接口,重写其中的compareTo()方法。
(2)部分排序:对最终输出的每一个文件进行内部排序。
(3)全排序:对所有数据进行排序,通常只有一个Reduce。
(4)二次排序:排序的条件有两个。
5)Combiner合并
Combiner合并可以提高程序执行效率,减少IO传输。但是使用时必须不能影响原有的业务处理结果。
6)逻辑处理接口:Reducer
用户根据业务需求实现其中三个方法:reduce() setup() cleanup ()
7)输出数据接口:OutputFormat
(1)默认实现类是TextOutputFormat,功能逻辑是:将每一个KV对,向目标文本文件输出一行。
(2)用户还可以自定义OutputFormat。
在driver中设置
// 开启map端输出压缩
conf.setBoolean("mapreduce.map.output.compress", true);
// 设置map端输出压缩方式
conf.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class,CompressionCodec.class);
// 设置reduce端输出压缩开启
FileOutputFormat.setCompressOutput(job, true);
// 设置压缩的方式
FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
// FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
// FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);
基础架构
ResouceManeger是整个集群资源的老大
NodeManager是单节点资源的老大
ApplicationMaster是每一个作业资源的老大
Yarn的工作机制
这张图也显示了MapReduce和Yarn的合作关系
MR程序提交到客户端所在的节点。
YarnRunner向ResourceManager申请一个Application。
RM将该应用程序的资源路径返回给YarnRunner。
该程序将运行所需资源提交到HDFS上。
程序资源提交完毕后,申请运行mrAppMaster。
RM将用户的请求初始化成一个Task。
其中一个NodeManager领取到Task任务。
该NodeManager创建容器Container,并产生MRAppmaster。
Container从HDFS上拷贝资源到本地。
MRAppmaster向RM 申请运行MapTask资源。
RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。
MR向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动MapTask,MapTask对数据分区排序。
MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。
ReduceTask向MapTask获取相应分区的数据。
程序运行完毕后,MR会向RM申请注销自己。
主要三种:FIFO,容量,公平
FIFO不支持多队列
容量和公平的相同点
不同点
(1)列出所有Application:
[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -list
2021-02-06 10:21:19,238 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of applications (application-types: [], states: [SUBMITTED, ACCEPTED, RUNNING] and tags: []):0
Application-Id Application-Name Application-Type User Queue State Final-State Progress Tracking-URL
(2)根据Application状态过滤:yarn application -list -appStates (所有状态:ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED)
[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -list -appStates FINISHED
2021-02-06 10:22:20,029 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of applications (application-types: [], states: [FINISHED] and tags: []):1
Application-Id Application-Name Application-Type User Queue State Final-State Progress Tracking-URL
application_1612577921195_0001 word count MAPREDUCE atguigu default FINISHED SUCCEEDED 100% http://hadoop102:19888/jobhistory/job/job_1612577921195_0001
(3)Kill掉Application:
[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -kill application_1612577921195_0001
2021-02-06 10:23:48,530 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Application application_1612577921195_0001 has already finished
(1)查询Application日志:yarn logs -applicationId
[atguigu@hadoop102 hadoop-3.1.3]$ yarn logs -applicationId application_1612577921195_0001
(2)查询Container日志:yarn logs -applicationId -containerId
[atguigu@hadoop102 hadoop-3.1.3]$ yarn logs -applicationId application_1612577921195_0001 -containerId container_1612577921195_0001_01_000001
(1)列出所有Application尝试的列表:yarn applicationattempt -list
[atguigu@hadoop102 hadoop-3.1.3]$ yarn applicationattempt -list application_1612577921195_0001
2021-02-06 10:26:54,195 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of application attempts :1
ApplicationAttempt-Id State AM-Container-Id Tracking-URL
appattempt_1612577921195_0001_000001 FINISHED container_1612577921195_0001_01_000001 http://hadoop103:8088/proxy/application_1612577921195_0001/
(2)打印ApplicationAttemp状态:yarn applicationattempt -status
[atguigu@hadoop102 hadoop-3.1.3]$ yarn applicationattempt -status appattempt_1612577921195_0001_000001
2021-02-06 10:27:55,896 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Application Attempt Report :
ApplicationAttempt-Id : appattempt_1612577921195_0001_000001
State : FINISHED
AMContainer : container_1612577921195_0001_01_000001
Tracking-URL : http://hadoop103:8088/proxy/application_1612577921195_0001/
RPC Port : 34756
AM Host : hadoop104
Diagnostics :
(1)列出所有Container:yarn container -list
[atguigu@hadoop102 hadoop-3.1.3]$ yarn container -list appattempt_1612577921195_0001_000001
2021-02-06 10:28:41,396 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of containers :0
Container-Id Start Time Finish Time State Host Node Http Address
(2)打印Container状态: yarn container -status
[atguigu@hadoop102 hadoop-3.1.3]$ yarn container -status container_1612577921195_0001_01_000001
2021-02-06 10:29:58,554 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Container with id 'container_1612577921195_0001_01_000001' doesn't exist in RM or Timeline Server.
注:只有在任务跑的途中才能看到container的状态
列出所有节点:yarn node -list -all
[atguigu@hadoop102 hadoop-3.1.3]$ yarn node -list -all
2021-02-06 10:31:36,962 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total Nodes:3
Node-Id Node-State Node-Http-Address Number-of-Running-Containers
hadoop103:38168 RUNNING hadoop103:8042 0
hadoop102:42012 RUNNING hadoop102:8042 0
hadoop104:39702 RUNNING hadoop104:8042 0
NameNode内存计算
每个文件块大概占用150byte,一台服务器128G内存为例,能存储多少文件块呢?
128 * 1024 * 1024 * 1024 / 150Byte ≈ 9.1亿
G MB KB Byte
当小文件过多,会占用过多的NameNode内存;每个文件都会开启一个MapTask,小文件过多会导致开启过多MapTask,启动时间比处理时间还长
将文件上传至HDFS前就先进行处理
我们可以使用HAR文件进行存档,HAR可以将小文件存入HDFS,并且可以透明访问。对于HDFS来说,仍然是很多小文件,但是对NameNode而言却是一个整体,这减少了NameNode的内存
开启uber模式,让同一个job的多个Task可以运行在一个JVM中,不用每个Task都开启JVM
数据倾斜优化方法:
mapper阶段
reduce阶段
减少数据倾斜:
检查空值过多产生的数据倾斜:过滤空值;保留空值,自定义分区
map阶段提前处理
增加reduce个数