1.高并发是访问解决性能问题,大数据是为了解决数据量逐渐慢慢变大,解决数据存储和数据分析(计算)问题!
2.面对的数据和计算难题
1.大量的网页如何存储,
2.搜索算法!(Luncene,solr,El.....)
3.keepalived 和zookeeper之间的区别?
keepalived和zookeeper都可以完成高可用,但是在Hadoop的源码里是集成了zookeeper的配置的,所以我们在hadoop中配置zookeeper的配置时,就很轻松,如果我们使用keepalived来实现hadoop的高可用,我们就要修改Hadoop以及Hbase的等等一些列的东东,所以我们做
大数据的高可用只会用到zookeeper!
而且zookeeper还会可以和传统项目集成来完成一系列的功能!
5.HDFS简介:
5.HDFS优点:
HDFS优点:
–高容错性
数据自动保存多个副本
副本丢失后,自动恢复
– 适合批处理
移动计算而非数据
数据位置暴露给计算框架
– 适合大数据处理
GB 、 TB 、甚至PB 级数据
百万规模以上的文件数量
10K+ 节点
– 可构建在廉价机器上
通过多副本提高可靠性
提供了容错和恢复 机制
6.HDFS缺点:
– 低延迟数据访问
比如毫秒级
低延迟与高吞吐率
– 小文件存取
占用NameNode 大量内存
寻道时间超过读取时间
– 并发写入、文件随机修改
一个文件只能有一个写者
仅支持append
注:Hadoop的缺点:更适合海量的大文件处理,如果都是小文件(1M,因为小文件的寻址时间要远大于其读取时间,还有一个是占用了过多的内存空间(小文件的元数据相对来说比较多),当然这些小文件可以优化,即先将小文件合并,再存储到HDFS上),貌似就不太适合处理!
Hadoop1.x默认的文件都是64M(块文件),Hadoop 2.x的文件块大小默认是128M。
例如(百度网盘上的文件只能修改文件名,内容不支持修改!虽然Hadoop2.x支持append,但是在生产环境下是不会开放的,因为HDFS会有多个副本,如果你修改一个,就需要同时修改多个副本,而且大文件是切分成多个小文件块存储的,但是你要修改一个小文件,可能原来的切分规则就要变了,也就是NameNode的元数据也需要修改,
高并发量的时候就容易出现NameNode的负载均衡问题,而且要先从大文件块中找出相对应的小文件也是很耗时的)
7.一定要学会看英文文档(最官方,而且到公司你是关键人物,很多技术需要自己啃,而学技术最捷径的就是英文文档,而且最新的技术本身都是老外发明出来的。如果人家都翻译出来了,基本上已经不是新技术了。)
8.Secondary NameNode是NameNode的部分备份节点,不是全部的备份哦(即:有一部分edits.new中的信息是丢失的),这一点要注意!
9.配置Hadoop集群的时候,集群的配置要保持一致,否则就会出错!
10.如果文件块的大小没有64M或者128M,那么它就是按照自己实际大小存储的,而且文件大小不到64M,或者128M,它是会按着自己的实际大小单独存成一个Block的(即:65M=64M+1M(默认块大小是64M),那么这个块只会占用64M,不会占用128M)!
11.副本数验证的时候,只会验证副本数大于等于你的配置,不是一定是等于!(例如,你突然将一台服务器的电源拔了,然后副本就会变为2份,然后它自动补成3份,当你将原来的那台再加上电的时候,现在副本数就成了4份,机架不会将4份中的一个副本删除,会保留这4份)!
12.什么时候导致数据倾斜?例如存储的时候,以及自己写脚本的时候都可能造成数据倾斜,HDFS为了防止这种情况,它的存储是随机存放的!
13.NameNode主要功能:
1) 接受客户端的读写服务
2) 保存metaData信息包括:
1.文件owership和permissions --------由fsimage文件记录(源文件持久化)
2.文件包含哪些块 -------由fsimage文件记录
3.Block保存在哪个DataNode(由DataNode启动时上报) ----- edits文件记录(记录你的操作日志)
NameNode的metadate信息在启动后会加载到内存
metadata存储到磁盘文件名为”fsimage”
Block的位置信息不会保存到fsimage
edits记录对metadata的操作日志
14.注意:fsimage和edits不会记录Block保存到哪个DataNode上面,这个由DataNode启动时自动上报,所以启动的时候要先启动NameNode,然后再启动Secondary NameNode,再启动DataNode节点!(NameNode自己是绝对不会主动合并fsimage和edits的)
15.edits文件变为edits.new时,edits.new文件是空的哦!
16.SNN合并流程:这是SNN主动做的,不是NameNode主动做的哦,所以当SNN挂掉的时候,NN是不做合并的,SNN合并的目的:当NameNode挂掉的时候,用于数据恢复,
当然也可以加快NameNode的启动,例如当NameNode一年了,它的edits文件就会很大很大,如果这时候没有SNN的主动合并,那么NameNode启动的时候就会很慢,它需要自动合并edits文件和fsimage文件,这会非常耗时,即由SNN来做这件事可以减少启动时间!
17.HDFS启动的时候首先会加载fsimage文件然后再加载edits文件,通过Secondary NameNode的主动合并成fsimage文件,最后将这个fsimage文件再推送回NN节点!
18.其实砸了SNN的时候也会出现数据丢失?其实综上:Secondary NameNode节点挂掉的话是不会丢失数据的,因为可以再启动一台Secondary NameNode,而NameNode节点挂掉的话,是会丢失一部分数据的(丢失的是edits.new文件)
19.SNN执行合并时机:(2种情况,符合任意一种都会执行合并!)
20.注意:SNN合并的时候是将NameNode节点上的fsimage和edits这两个文件抓取到SNN节点上,而不是将NameNode节点上的fsimage文件和edits文件中的
21.SNN是Hadoop1.x中的,但是Hadoop2.x也是带了SNN,这是因为Hadoop在没有做高可用的时候,我们可以用SNN做高可用(即在hadoop2.x中如果NameNode没有做高可用,是会用到这个SNN)!
22.在做实验的时候,有可能NameNode和Secondary NameNode是可能出现节点公用的。但是生成环境下是不会这样配置的,这样就不高可用和安全!
23.edits.new文件也是在硬盘上生成的,当NameNode突然挂机(如果是断电)的时候,edits.new文件是会转化成edits文件的!
edits.new文件也是在硬盘上生成的,当NameNode突然挂机(如果是砸电脑,机子都破坏了)的时候,edits.new和fsimage文件的内容就丢失了,实际上这个edits文件到edits.new文件之间的部分就丢失了!
24.edits挂掉的2种情况:
断电:
砸机子:
25.edits.new文件是在内存中的?是在硬盘上会生成edits.new文件
26.Block的副本放置策略:
– 第一个副本(找一个负载低的):放置在上传文件的DN;如果
是集群外提交,则随机挑选一台磁盘不太
满,CPU不太忙的节点。
– 第二个副本:放置在于第一个副本不同的
机架的节点上。
– 第三个副本:与第二个副本相同机架的节
点。
– 更多副本:随机节点
27.HDFS写流程+HDFS读流程 见尚学堂课件(PDF版)!)
28.HDFS是简单匹配通过用户名的匹配,操作文件的(通过用户名(登录者)来交给NameNode验证)!
29.HDFS读数据块的时候,它会找一个最近的节点读,然后读的时候是顺序读!(不是并发读哦:因为如果是并发读的话,你需要将1TB的文件先读出来在客户端再在内存中组装,这其实对于客户端是办不到的,写在客户端,其实也是顺序执行的,只是在一个Datanode写完一个块的时候,这个块会自己复制到第二个,第三个DataNode节点上!)
30.文件用户:补充??
31.HDFS安全模式下是不会新创建一个新的fsimage文件的吧?
32.实际生产中一般都是用64位的Hadoop版本的!
34.做集群的时候一定要注意的是:
1.时间同步(ntpdate)---------必选项
2./etc/hosts文件做一个映射
3.虚拟机基本信息的时候,做一个快照!当Hadoop集群配置完成的时候,来一个快照!
35.SNN节点实际上就是根据fsimage文件会根据edits操作日志文件来生成想对应的fsimage元数据文件的!
36.SNN执行合并的时机:( SNN不是NN的备份(但可以做备份),它的主要工作是帮助NN合并editslog,减少NN启动时间)
根据配置文件设置的时间间隔fs.checkpoint.period 默认3600秒
根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB
37. DataNode(DN)
– 存储数据(Block)
– 启动DN线程的时候会向NN汇报block信息
– 通过向NN发送心跳保持与其联系(3秒一次),如果NN 10分钟没有收到DN的心跳,则认为其已经lost,并copy其上的block到其它DN
38.HDFS文件权限
– 与Linux文件权限类似
r: read; w:write; x:execute,权限x对于文件忽略,对于文件夹表示是否允许访问其内容
– 如果Linux系统用户zhangsan使用hadoop命令创建一个文件,那么这个文件在HDFS中owner就是zhangsan。
– HDFS的权限目的:阻止好人错错事,而不是阻止坏人做坏事。 HDFS相信,你告诉我你是谁,我就认为你是谁
39.安全模式
– namenode启动的时候,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作。
– 一旦在内存中成功建立文件系统元数据的映射,则创建一个新的fsimage文件(这个操作不需要SecondaryNameNode)和一个空的编辑日志。
– 此刻namenode运行在安全模式。即namenode的文件系统对于客服端来说是只读的。 (显示目录,显示文件内容等。写、删除、重命名都会失败)。
– 在此阶段Namenode收集各个datanode的报告,当数据块达到最小副本数以上时,会被认为是“安全”的, 在一定比例(可设置)的数据块被确定为“安全”后,再过若干时间,安全模式结束
– 当检测到副本数不足的数据块时,该块会被复制直到达到最小副本数,系统中数据块的位置并不是由namenode维护的,而是以块列表形式存储在datanode中。
40.搭建之前看文档,搭建过程中出现问题的时候:
1.首先看控制台错误信息,
2.再去日志文件中用tail命令看日志文件的错误信息;
41.伪分布式:可以在测试的时候使用,
完全分布式:在生产或者公司中使用!
42.生产环境下不会进行节点共用(即生产环境不会让NameNode和Secondary NameNode在同一台节点上!)
43.实际生产环境下是不允许将datanode上的数据放在/tmp(Linux系统的/tmp目录的,倒是可以在Hadoop的安装目录下创建一个/tmp目录,然后将文件放到里面) 目录下,这个目录下的文件一开机、一关机就会丢失!
44.
HDFS:(其实HDFS的配置也就是对:NameNode+DataNode+Secondary NameNode的配置)
NameNode -------------->在Core-site.xml文件下配置一下,(注意:这个tmp目录最好也配置一下,也可以是默认配置,当然要在官网上查core-default.xml文档才知道它的默认路径在哪儿):
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
</configuration>
DataNode --------------> Slaves文件
Secondary NameNode----->masters文件(自己创建)
45.节点分布划分:
NN SNN DN
node1 1
node2 1 1
node3 1
node4 1
注意:生产环境下:Linux要用英文版(英文输入法,英文显示啥的,最多只是在安装过程中用中文)!
46.完全分布式安装之前的准备:
1、时间同步(ntpdate -u 国内的时间服务器地址!),网络配置通,hosts文件,主机名,关闭防火墙!)----------所有的集群安装首先第一步要做的就是时间同步!
yum -y install ntp ntpdate 时间服务器
ntpdate -u s1a.time.edu.cn 时间同步 注:s1a.time.edu.cn 北京邮电大学NTP服务器地址(通过百度搜索:国内ntp服务器域名 得到)
2.JDK安装(1.7),同时在/etc/profile文件和hadoop安装目录的etc/hadoop/hadoop-env.sh文件中配置一下JAVA_HOME,在/etc/profile目录下还需要将JAVA_HOME目录下的bin目录放到PATH路径之后!
3.SSH免秘钥登录(NameNode和DataNode之间需要通信,所以也需要配置NameNode和DataNode之间的免秘钥以及它们各自自己的免密码登录)!
只要将node01节点上的id_dsa.pub(公钥文件或者id_rsa.pub文件)内容追加(authorized_keys)即将主节点上的ssh的公钥文件内容追加到要无秘钥连接的用户目录下的.ssh文件夹下的authorized_keys!
(在node01上: scp /root/.ssh/id_dsa.pub root@node02:/root/
然后在node02上: cat /root/id_dsa.pub >> (追加) /root/.ssh/authorized_keys 即可;做到这里就可以进行node01到node02的无秘钥连接,但是此时别的机子是不能对node01进行无秘钥连接的!
)
4.修改配置文件并同步配置文件到各个节点(以下的配置文件都是在hadoop的安装目录的etc/hadoop文件夹下)
1). hadoop-env.sh文件中配置一下JAVA_HOME
export JAVA_HOME=/usr/java/jdk1.7.0_67
2). core-site.xml文件中:配置NameNode的服务器地址:以及tmp临时目录:(这个临时目录最好是在hadoop的安装目录,这个目录要么为空,要么不存在,这点要特别注意)
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
</configuration>
注:.hadoop.tmp.dir要求要么不存在,要么是空!(注意:如果在配置过程中出了问题,你还格式化了,这时候你就需要将这个目录下的文件全部删除,然后将文件配置正确,然后重新格式化)
3).在hadoop的安装目录的etc/hadoop文件夹下手动创建masters ,然后在这个masters文件中指定secondary NameNode节点的IP或者主机名!
node2
4).在slaves文件中配置datanode节点是哪几台(datanode的hostname或者ip)
node2
node3
node4
5).在hdfs文件中配置(副本数。以及secondary NameNode的webui请求路径(http请求))如下:
<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node2:50090</value>
</property>
</configuration>
5.将这个hadoop安装目录配置好的目录整体拷贝到其它主机节点上与本机路径相同的目录下!
同时在所有的节点的/etc/profile文件中配置 HADOOP_HOME(Hadoop安装目录),以及将这个Hadoop目录下的bin目录和sbin目录export追加到PATH路径下,
这样在其它地方使用这两个目录(hadoop/bin;hadoop/sbin目录)的命令,就不用非得跑到hadoop的安装目录下了!
5.格式化NameNode: bin/hdfs namenode -format (在NameNode节点也即主节点上执行这条命令)
注:格式化会生成HDFS的fsimage文件好edits文件!
6.启动
sbin/start-dfs.sh
出了问题,看控制台的信息是Info级别还是有Error级别的,logs目录下的日志,找到是namenode出错还是datanode出错还是secondary namenode出错,看日志就好!
看错误日志的时候,看.log文件,而不要看.out文件!遇到错误问题一定要看日志============!
注意:1.各个节点上的hadoop的配置必须是一样的,否则会出错!
2.如果格式化出错,就必须将自己在core-site.xml文件中配置的tmp目录全部删除,如果存在这个目录,我们再格式化的时候也会出问题:
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
47.安装yum源
利用nginx挂载本地的目录(ISO文件)---------》(yum源搭建局域网流程理解)
1).先将虚拟机的CD/DVD使用ISO镜像文件选定ISO文件!
mount /dev/cdrom /mnt挂载(搭建本地yum源)
这样我们就搭建了一个本地的软件源,!
2).首先修改:/etc/yum.repos.d/CentOS-Base.repo文件:
[base]
name=CentOS-Local
baseurl=http://node1(这个hostname也可以换成ip地址)
#baseurl=file:///mnt/(这个是注释掉的,当然也可以直接就连接到本地,而不用通过nginx)
gpgcheck=0
3).然后在nginx的nginx.conf文件中配置:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /mnt;===================================(尤其是要注意这里:)
autoindex on;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
4).然后启动nginx
5).这样再在我们的windows电脑的C:\Windows\System32\drivers\etc\hosts文件中修改node1对应的ip映射,这样我们就可以直接
在我们的浏览器中访问挂载到/mnt目录下的yum源了!(当然当我们直接用yum install 的时候,yum首先会到/etc/yum.repos.d/CentOS-Base.repo
文件中查找yum源,也就是baseurl那个hostname(ip,这个ip是nginx所在服务器的ip哦),然后这个ip就会发送给nginx服务器,nginx服务器帮助我们将我们访问已经挂载到/mnt目录下的本地ISO yum源)
注意:当然这里我们可以直接通过修改/etc/yum.repos.d/CentOS-Base.repo文件的baseurl为本地源(我们已经将ISO挂载的目录/mnt),如下所示:
1). 先将虚拟机的CD/DVD使用ISO镜像文件选定ISO文件!
2). mount /dev/cdrom /mnt挂载(搭建本地yum源)
这样我们就搭建了一个本地的软件源,!
3).修改:/etc/yum.repos.d/CentOS-Base.repo文件:
[base]
name=CentOS-Local
baseurl=file:///mnt/(这个是注释掉的,当然也可以直接就连接到本地,而不用通过nginx)
gpgcheck=0
这样当我们用yum install 的时候,yum就会先到这个文件中查找yum源,结果一看yum源就在我们本地的/mnt目录下,然后yum就会自动去这个文件夹下
找相对应的要安装的软件包!
上面的也是yum源的解析过程的完整版!通过上述我们也知道如果在/etc/yum.repos.d/CentOS-Base.repo文件中我们配置的yum源是aliyun.com或者其它的yum源,
如果我们要使用yum 来安装软件,实际上我们是需要先联网的!
52.在Eclipse用HADOOP的插件的时候,我们在新建一个M/R时,是需要将Use M/R Master host 的勾选号去掉的,然后再配置我们HDFS所在的服务器的ip和端口号(一般为9000,9000是RPC入口)!
你说的是Windows上的用户名和Linux系统的启动hadoop用户名要相同吧(windows用户名的修改在计算机---》管理----》用户、用户组那里修改)!
52.实际生产中是不会将Hadoop的用户名权限验证给去掉的,这样是为了安全!而且我们一般不会修改HDFS上面的用户,所以实际生产中我们都是修改windows的用户名!
注意:修改的是windows的用户名,不是主机名;这两者有区别!
53.HDFS默认用户名就是我们搭建Hadoop的用户root,HDFS权限验证默认就是开启的,通过用户名匹配的模式!
HDFS说到底是个文件系统,格式化的目的是让它生效,相当于给硬盘打格子使用!
56.xshell可以同时操作多个窗口:选定全部会话,然后在下面的栏里输入操作命令即可!
57.// 加载src目录下的配置文件(src目录下默认的配置文件应该包括:core-site.xml,hdfs-site.xml文件)
conf = new Configuration();
fs = FileSystem.get(conf)
58.对于HDFS的上传和下载主要是靠FileSystem的OutputStream流和InputStream流!
59.我们安装集群的时候都会关掉防火墙,实际生产中也会这样关闭吗?
分情况:
1.有可能公司会在最前面挡一台防火墙:后面我们配置的服务器就不需要了!
2.我们需要将我们的配置的服务器的ip和端口号交给运维人员,让他们给整一下!
60.在安装ssh无秘钥连接的时候known_hosts文件可以删除吗?这里面记录的是什么来着?
known_hosts记录的是连接记录,如果我们删除的话,会每次连接的时候让你输入yes验证,所以我们一般不删除!
61,Linux系统只能是centos 6.x吗?
centos6.x的配置文件和命令都与6.x有区别,所以这里我们只用6.x的!
62.如果windows电脑的用户名和linux配置hadoop的名字不一致,可以通过上传文件,看Eclipse的报错信息!看是否是用户名一致问题造成的!
63.在eclipse中写代码的时候,要首先将core-site.xml文件和hdfs-site.xml文件加载到我们创建项目的src目录下!
64.一些简单的代码实现文件上传和下载,创建目录等基本功能!
package com.sxt.hdfs;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HdfsDemo {
FileSystem fs;
Configuration conf;
@Before
public void begin() throws Exception {
// 加载src目录下的配置文件
conf = new Configuration();
fs = FileSystem.get(conf);
}
@After
public void end() {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void mkdir() throws Exception {
Path path = new Path("/tmp");
fs.mkdirs(path);
}
@Test
public void upload() throws Exception {
Path path = new Path("/tmp/test");
FSDataOutputStream outputStream = fs.create(path);
FileUtils.copyFile(new File("D://test.txt"), outputStream);
}
@Test
public void list() throws Exception {
Path path = new Path("/tmp");
FileStatus[] fss = fs.listStatus(path);
for (FileStatus s : fss) {
System.out.println(s.getPath() + "-" + s.getLen() + "-" + s.getAccessTime());
}
}
@Test
public void upload2() throws Exception {
Path path = new Path("/tmp/seq");
SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, path, Text.class, Text.class);
File file = new File("D://test");
for(File f : file.listFiles()) {
writer.append(new Text(f.getName()), new Text(FileUtils.readFileToString(f)));
}
}
@Test
public void download2() throws Exception {
Path path = new Path("/tmp/seq");
SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);
Text key = new Text();
Text value = new Text();
while(reader.next(key, value)) {
System.out.println(key);
System.out.println(value);
System.out.println("--------------");
}
}
}
2.面对的数据和计算难题
1.大量的网页如何存储,
2.搜索算法!(Luncene,solr,El.....)
3.keepalived 和zookeeper之间的区别?
keepalived和zookeeper都可以完成高可用,但是在Hadoop的源码里是集成了zookeeper的配置的,所以我们在hadoop中配置zookeeper的配置时,就很轻松,如果我们使用keepalived来实现hadoop的高可用,我们就要修改Hadoop以及Hbase的等等一些列的东东,所以我们做
大数据的高可用只会用到zookeeper!
而且zookeeper还会可以和传统项目集成来完成一系列的功能!
5.HDFS简介:
5.HDFS优点:
HDFS优点:
–高容错性
数据自动保存多个副本
副本丢失后,自动恢复
– 适合批处理
移动计算而非数据
数据位置暴露给计算框架
– 适合大数据处理
GB 、 TB 、甚至PB 级数据
百万规模以上的文件数量
10K+ 节点
– 可构建在廉价机器上
通过多副本提高可靠性
提供了容错和恢复 机制
6.HDFS缺点:
– 低延迟数据访问
比如毫秒级
低延迟与高吞吐率
– 小文件存取
占用NameNode 大量内存
寻道时间超过读取时间
– 并发写入、文件随机修改
一个文件只能有一个写者
仅支持append
注:Hadoop的缺点:更适合海量的大文件处理,如果都是小文件(1M,因为小文件的寻址时间要远大于其读取时间,还有一个是占用了过多的内存空间(小文件的元数据相对来说比较多),当然这些小文件可以优化,即先将小文件合并,再存储到HDFS上),貌似就不太适合处理!
Hadoop1.x默认的文件都是64M(块文件),Hadoop 2.x的文件块大小默认是128M。
例如(百度网盘上的文件只能修改文件名,内容不支持修改!虽然Hadoop2.x支持append,但是在生产环境下是不会开放的,因为HDFS会有多个副本,如果你修改一个,就需要同时修改多个副本,而且大文件是切分成多个小文件块存储的,但是你要修改一个小文件,可能原来的切分规则就要变了,也就是NameNode的元数据也需要修改,
高并发量的时候就容易出现NameNode的负载均衡问题,而且要先从大文件块中找出相对应的小文件也是很耗时的)
7.一定要学会看英文文档(最官方,而且到公司你是关键人物,很多技术需要自己啃,而学技术最捷径的就是英文文档,而且最新的技术本身都是老外发明出来的。如果人家都翻译出来了,基本上已经不是新技术了。)
8.Secondary NameNode是NameNode的部分备份节点,不是全部的备份哦(即:有一部分edits.new中的信息是丢失的),这一点要注意!
9.配置Hadoop集群的时候,集群的配置要保持一致,否则就会出错!
10.如果文件块的大小没有64M或者128M,那么它就是按照自己实际大小存储的,而且文件大小不到64M,或者128M,它是会按着自己的实际大小单独存成一个Block的(即:65M=64M+1M(默认块大小是64M),那么这个块只会占用64M,不会占用128M)!
11.副本数验证的时候,只会验证副本数大于等于你的配置,不是一定是等于!(例如,你突然将一台服务器的电源拔了,然后副本就会变为2份,然后它自动补成3份,当你将原来的那台再加上电的时候,现在副本数就成了4份,机架不会将4份中的一个副本删除,会保留这4份)!
12.什么时候导致数据倾斜?例如存储的时候,以及自己写脚本的时候都可能造成数据倾斜,HDFS为了防止这种情况,它的存储是随机存放的!
13.NameNode主要功能:
1) 接受客户端的读写服务
2) 保存metaData信息包括:
1.文件owership和permissions --------由fsimage文件记录(源文件持久化)
2.文件包含哪些块 -------由fsimage文件记录
3.Block保存在哪个DataNode(由DataNode启动时上报) ----- edits文件记录(记录你的操作日志)
NameNode的metadate信息在启动后会加载到内存
metadata存储到磁盘文件名为”fsimage”
Block的位置信息不会保存到fsimage
edits记录对metadata的操作日志
14.注意:fsimage和edits不会记录Block保存到哪个DataNode上面,这个由DataNode启动时自动上报,所以启动的时候要先启动NameNode,然后再启动Secondary NameNode,再启动DataNode节点!(NameNode自己是绝对不会主动合并fsimage和edits的)
15.edits文件变为edits.new时,edits.new文件是空的哦!
16.SNN合并流程:这是SNN主动做的,不是NameNode主动做的哦,所以当SNN挂掉的时候,NN是不做合并的,SNN合并的目的:当NameNode挂掉的时候,用于数据恢复,
当然也可以加快NameNode的启动,例如当NameNode一年了,它的edits文件就会很大很大,如果这时候没有SNN的主动合并,那么NameNode启动的时候就会很慢,它需要自动合并edits文件和fsimage文件,这会非常耗时,即由SNN来做这件事可以减少启动时间!
17.HDFS启动的时候首先会加载fsimage文件然后再加载edits文件,通过Secondary NameNode的主动合并成fsimage文件,最后将这个fsimage文件再推送回NN节点!
18.其实砸了SNN的时候也会出现数据丢失?其实综上:Secondary NameNode节点挂掉的话是不会丢失数据的,因为可以再启动一台Secondary NameNode,而NameNode节点挂掉的话,是会丢失一部分数据的(丢失的是edits.new文件)
19.SNN执行合并时机:(2种情况,符合任意一种都会执行合并!)
20.注意:SNN合并的时候是将NameNode节点上的fsimage和edits这两个文件抓取到SNN节点上,而不是将NameNode节点上的fsimage文件和edits文件中的
21.SNN是Hadoop1.x中的,但是Hadoop2.x也是带了SNN,这是因为Hadoop在没有做高可用的时候,我们可以用SNN做高可用(即在hadoop2.x中如果NameNode没有做高可用,是会用到这个SNN)!
22.在做实验的时候,有可能NameNode和Secondary NameNode是可能出现节点公用的。但是生成环境下是不会这样配置的,这样就不高可用和安全!
23.edits.new文件也是在硬盘上生成的,当NameNode突然挂机(如果是断电)的时候,edits.new文件是会转化成edits文件的!
edits.new文件也是在硬盘上生成的,当NameNode突然挂机(如果是砸电脑,机子都破坏了)的时候,edits.new和fsimage文件的内容就丢失了,实际上这个edits文件到edits.new文件之间的部分就丢失了!
24.edits挂掉的2种情况:
断电:
砸机子:
25.edits.new文件是在内存中的?是在硬盘上会生成edits.new文件
26.Block的副本放置策略:
– 第一个副本(找一个负载低的):放置在上传文件的DN;如果
是集群外提交,则随机挑选一台磁盘不太
满,CPU不太忙的节点。
– 第二个副本:放置在于第一个副本不同的
机架的节点上。
– 第三个副本:与第二个副本相同机架的节
点。
– 更多副本:随机节点
27.HDFS写流程+HDFS读流程 见尚学堂课件(PDF版)!)
28.HDFS是简单匹配通过用户名的匹配,操作文件的(通过用户名(登录者)来交给NameNode验证)!
29.HDFS读数据块的时候,它会找一个最近的节点读,然后读的时候是顺序读!(不是并发读哦:因为如果是并发读的话,你需要将1TB的文件先读出来在客户端再在内存中组装,这其实对于客户端是办不到的,写在客户端,其实也是顺序执行的,只是在一个Datanode写完一个块的时候,这个块会自己复制到第二个,第三个DataNode节点上!)
30.文件用户:补充??
31.HDFS安全模式下是不会新创建一个新的fsimage文件的吧?
32.实际生产中一般都是用64位的Hadoop版本的!
34.做集群的时候一定要注意的是:
1.时间同步(ntpdate)---------必选项
2./etc/hosts文件做一个映射
3.虚拟机基本信息的时候,做一个快照!当Hadoop集群配置完成的时候,来一个快照!
35.SNN节点实际上就是根据fsimage文件会根据edits操作日志文件来生成想对应的fsimage元数据文件的!
36.SNN执行合并的时机:( SNN不是NN的备份(但可以做备份),它的主要工作是帮助NN合并editslog,减少NN启动时间)
根据配置文件设置的时间间隔fs.checkpoint.period 默认3600秒
根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB
37. DataNode(DN)
– 存储数据(Block)
– 启动DN线程的时候会向NN汇报block信息
– 通过向NN发送心跳保持与其联系(3秒一次),如果NN 10分钟没有收到DN的心跳,则认为其已经lost,并copy其上的block到其它DN
38.HDFS文件权限
– 与Linux文件权限类似
r: read; w:write; x:execute,权限x对于文件忽略,对于文件夹表示是否允许访问其内容
– 如果Linux系统用户zhangsan使用hadoop命令创建一个文件,那么这个文件在HDFS中owner就是zhangsan。
– HDFS的权限目的:阻止好人错错事,而不是阻止坏人做坏事。 HDFS相信,你告诉我你是谁,我就认为你是谁
39.安全模式
– namenode启动的时候,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作。
– 一旦在内存中成功建立文件系统元数据的映射,则创建一个新的fsimage文件(这个操作不需要SecondaryNameNode)和一个空的编辑日志。
– 此刻namenode运行在安全模式。即namenode的文件系统对于客服端来说是只读的。 (显示目录,显示文件内容等。写、删除、重命名都会失败)。
– 在此阶段Namenode收集各个datanode的报告,当数据块达到最小副本数以上时,会被认为是“安全”的, 在一定比例(可设置)的数据块被确定为“安全”后,再过若干时间,安全模式结束
– 当检测到副本数不足的数据块时,该块会被复制直到达到最小副本数,系统中数据块的位置并不是由namenode维护的,而是以块列表形式存储在datanode中。
40.搭建之前看文档,搭建过程中出现问题的时候:
1.首先看控制台错误信息,
2.再去日志文件中用tail命令看日志文件的错误信息;
41.伪分布式:可以在测试的时候使用,
完全分布式:在生产或者公司中使用!
42.生产环境下不会进行节点共用(即生产环境不会让NameNode和Secondary NameNode在同一台节点上!)
43.实际生产环境下是不允许将datanode上的数据放在/tmp(Linux系统的/tmp目录的,倒是可以在Hadoop的安装目录下创建一个/tmp目录,然后将文件放到里面) 目录下,这个目录下的文件一开机、一关机就会丢失!
44.
HDFS:(其实HDFS的配置也就是对:NameNode+DataNode+Secondary NameNode的配置)
NameNode -------------->在Core-site.xml文件下配置一下,(注意:这个tmp目录最好也配置一下,也可以是默认配置,当然要在官网上查core-default.xml文档才知道它的默认路径在哪儿):
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
</configuration>
DataNode --------------> Slaves文件
Secondary NameNode----->masters文件(自己创建)
45.节点分布划分:
NN SNN DN
node1 1
node2 1 1
node3 1
node4 1
注意:生产环境下:Linux要用英文版(英文输入法,英文显示啥的,最多只是在安装过程中用中文)!
46.完全分布式安装之前的准备:
1、时间同步(ntpdate -u 国内的时间服务器地址!),网络配置通,hosts文件,主机名,关闭防火墙!)----------所有的集群安装首先第一步要做的就是时间同步!
yum -y install ntp ntpdate 时间服务器
ntpdate -u s1a.time.edu.cn 时间同步 注:s1a.time.edu.cn 北京邮电大学NTP服务器地址(通过百度搜索:国内ntp服务器域名 得到)
2.JDK安装(1.7),同时在/etc/profile文件和hadoop安装目录的etc/hadoop/hadoop-env.sh文件中配置一下JAVA_HOME,在/etc/profile目录下还需要将JAVA_HOME目录下的bin目录放到PATH路径之后!
3.SSH免秘钥登录(NameNode和DataNode之间需要通信,所以也需要配置NameNode和DataNode之间的免秘钥以及它们各自自己的免密码登录)!
只要将node01节点上的id_dsa.pub(公钥文件或者id_rsa.pub文件)内容追加(authorized_keys)即将主节点上的ssh的公钥文件内容追加到要无秘钥连接的用户目录下的.ssh文件夹下的authorized_keys!
(在node01上: scp /root/.ssh/id_dsa.pub root@node02:/root/
然后在node02上: cat /root/id_dsa.pub >> (追加) /root/.ssh/authorized_keys 即可;做到这里就可以进行node01到node02的无秘钥连接,但是此时别的机子是不能对node01进行无秘钥连接的!
)
4.修改配置文件并同步配置文件到各个节点(以下的配置文件都是在hadoop的安装目录的etc/hadoop文件夹下)
1). hadoop-env.sh文件中配置一下JAVA_HOME
export JAVA_HOME=/usr/java/jdk1.7.0_67
2). core-site.xml文件中:配置NameNode的服务器地址:以及tmp临时目录:(这个临时目录最好是在hadoop的安装目录,这个目录要么为空,要么不存在,这点要特别注意)
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
</configuration>
注:.hadoop.tmp.dir要求要么不存在,要么是空!(注意:如果在配置过程中出了问题,你还格式化了,这时候你就需要将这个目录下的文件全部删除,然后将文件配置正确,然后重新格式化)
3).在hadoop的安装目录的etc/hadoop文件夹下手动创建masters ,然后在这个masters文件中指定secondary NameNode节点的IP或者主机名!
node2
4).在slaves文件中配置datanode节点是哪几台(datanode的hostname或者ip)
node2
node3
node4
5).在hdfs文件中配置(副本数。以及secondary NameNode的webui请求路径(http请求))如下:
<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node2:50090</value>
</property>
</configuration>
5.将这个hadoop安装目录配置好的目录整体拷贝到其它主机节点上与本机路径相同的目录下!
同时在所有的节点的/etc/profile文件中配置 HADOOP_HOME(Hadoop安装目录),以及将这个Hadoop目录下的bin目录和sbin目录export追加到PATH路径下,
这样在其它地方使用这两个目录(hadoop/bin;hadoop/sbin目录)的命令,就不用非得跑到hadoop的安装目录下了!
5.格式化NameNode: bin/hdfs namenode -format (在NameNode节点也即主节点上执行这条命令)
注:格式化会生成HDFS的fsimage文件好edits文件!
6.启动
sbin/start-dfs.sh
出了问题,看控制台的信息是Info级别还是有Error级别的,logs目录下的日志,找到是namenode出错还是datanode出错还是secondary namenode出错,看日志就好!
看错误日志的时候,看.log文件,而不要看.out文件!遇到错误问题一定要看日志============!
注意:1.各个节点上的hadoop的配置必须是一样的,否则会出错!
2.如果格式化出错,就必须将自己在core-site.xml文件中配置的tmp目录全部删除,如果存在这个目录,我们再格式化的时候也会出问题:
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop</value>
</property>
47.安装yum源
利用nginx挂载本地的目录(ISO文件)---------》(yum源搭建局域网流程理解)
1).先将虚拟机的CD/DVD使用ISO镜像文件选定ISO文件!
mount /dev/cdrom /mnt挂载(搭建本地yum源)
这样我们就搭建了一个本地的软件源,!
2).首先修改:/etc/yum.repos.d/CentOS-Base.repo文件:
[base]
name=CentOS-Local
baseurl=http://node1(这个hostname也可以换成ip地址)
#baseurl=file:///mnt/(这个是注释掉的,当然也可以直接就连接到本地,而不用通过nginx)
gpgcheck=0
3).然后在nginx的nginx.conf文件中配置:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /mnt;===================================(尤其是要注意这里:)
autoindex on;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
4).然后启动nginx
5).这样再在我们的windows电脑的C:\Windows\System32\drivers\etc\hosts文件中修改node1对应的ip映射,这样我们就可以直接
在我们的浏览器中访问挂载到/mnt目录下的yum源了!(当然当我们直接用yum install 的时候,yum首先会到/etc/yum.repos.d/CentOS-Base.repo
文件中查找yum源,也就是baseurl那个hostname(ip,这个ip是nginx所在服务器的ip哦),然后这个ip就会发送给nginx服务器,nginx服务器帮助我们将我们访问已经挂载到/mnt目录下的本地ISO yum源)
注意:当然这里我们可以直接通过修改/etc/yum.repos.d/CentOS-Base.repo文件的baseurl为本地源(我们已经将ISO挂载的目录/mnt),如下所示:
1). 先将虚拟机的CD/DVD使用ISO镜像文件选定ISO文件!
2). mount /dev/cdrom /mnt挂载(搭建本地yum源)
这样我们就搭建了一个本地的软件源,!
3).修改:/etc/yum.repos.d/CentOS-Base.repo文件:
[base]
name=CentOS-Local
baseurl=file:///mnt/(这个是注释掉的,当然也可以直接就连接到本地,而不用通过nginx)
gpgcheck=0
这样当我们用yum install 的时候,yum就会先到这个文件中查找yum源,结果一看yum源就在我们本地的/mnt目录下,然后yum就会自动去这个文件夹下
找相对应的要安装的软件包!
上面的也是yum源的解析过程的完整版!通过上述我们也知道如果在/etc/yum.repos.d/CentOS-Base.repo文件中我们配置的yum源是aliyun.com或者其它的yum源,
如果我们要使用yum 来安装软件,实际上我们是需要先联网的!
52.在Eclipse用HADOOP的插件的时候,我们在新建一个M/R时,是需要将Use M/R Master host 的勾选号去掉的,然后再配置我们HDFS所在的服务器的ip和端口号(一般为9000,9000是RPC入口)!
你说的是Windows上的用户名和Linux系统的启动hadoop用户名要相同吧(windows用户名的修改在计算机---》管理----》用户、用户组那里修改)!
52.实际生产中是不会将Hadoop的用户名权限验证给去掉的,这样是为了安全!而且我们一般不会修改HDFS上面的用户,所以实际生产中我们都是修改windows的用户名!
注意:修改的是windows的用户名,不是主机名;这两者有区别!
53.HDFS默认用户名就是我们搭建Hadoop的用户root,HDFS权限验证默认就是开启的,通过用户名匹配的模式!
HDFS说到底是个文件系统,格式化的目的是让它生效,相当于给硬盘打格子使用!
56.xshell可以同时操作多个窗口:选定全部会话,然后在下面的栏里输入操作命令即可!
57.// 加载src目录下的配置文件(src目录下默认的配置文件应该包括:core-site.xml,hdfs-site.xml文件)
conf = new Configuration();
fs = FileSystem.get(conf)
58.对于HDFS的上传和下载主要是靠FileSystem的OutputStream流和InputStream流!
59.我们安装集群的时候都会关掉防火墙,实际生产中也会这样关闭吗?
分情况:
1.有可能公司会在最前面挡一台防火墙:后面我们配置的服务器就不需要了!
2.我们需要将我们的配置的服务器的ip和端口号交给运维人员,让他们给整一下!
60.在安装ssh无秘钥连接的时候known_hosts文件可以删除吗?这里面记录的是什么来着?
known_hosts记录的是连接记录,如果我们删除的话,会每次连接的时候让你输入yes验证,所以我们一般不删除!
61,Linux系统只能是centos 6.x吗?
centos6.x的配置文件和命令都与6.x有区别,所以这里我们只用6.x的!
62.如果windows电脑的用户名和linux配置hadoop的名字不一致,可以通过上传文件,看Eclipse的报错信息!看是否是用户名一致问题造成的!
63.在eclipse中写代码的时候,要首先将core-site.xml文件和hdfs-site.xml文件加载到我们创建项目的src目录下!
64.一些简单的代码实现文件上传和下载,创建目录等基本功能!
package com.sxt.hdfs;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HdfsDemo {
FileSystem fs;
Configuration conf;
@Before
public void begin() throws Exception {
// 加载src目录下的配置文件
conf = new Configuration();
fs = FileSystem.get(conf);
}
@After
public void end() {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void mkdir() throws Exception {
Path path = new Path("/tmp");
fs.mkdirs(path);
}
@Test
public void upload() throws Exception {
Path path = new Path("/tmp/test");
FSDataOutputStream outputStream = fs.create(path);
FileUtils.copyFile(new File("D://test.txt"), outputStream);
}
@Test
public void list() throws Exception {
Path path = new Path("/tmp");
FileStatus[] fss = fs.listStatus(path);
for (FileStatus s : fss) {
System.out.println(s.getPath() + "-" + s.getLen() + "-" + s.getAccessTime());
}
}
@Test
public void upload2() throws Exception {
Path path = new Path("/tmp/seq");
SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, path, Text.class, Text.class);
File file = new File("D://test");
for(File f : file.listFiles()) {
writer.append(new Text(f.getName()), new Text(FileUtils.readFileToString(f)));
}
}
@Test
public void download2() throws Exception {
Path path = new Path("/tmp/seq");
SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);
Text key = new Text();
Text value = new Text();
while(reader.next(key, value)) {
System.out.println(key);
System.out.println(value);
System.out.println("--------------");
}
}
}