Hadoop (一)
01hadoop历史、hadoop存储模型、架构模型、读写流程、伪分布式安装
01
场景一:现在有1T 文件,数字,行存储。其中有两行文本是相同的。找出这两行。
第一步:用hashcode的方式来进行遍历,把每行来存成文件,那么这个文件可以以hashcode来命名。最后会形成一堆的文件,文件的内容是行的内容。当遍历到相同的行时,只需要放在相同hashcode的文件中即可;
第二步:遍历每一个文件,只要遍历两个hashcode相同的,那么就找到了两行相同的文本。
用多个服务器来进行优化,但是如果只有一个服务器,该怎样来进行优化?(内存不够)
将一台服务器变多台;有没有必要生成这么多文件?
能够一次性的把文件加载到内存中即可,hashcode作为文件的名称是第一步,可以对hashcode来取模,得到的余数作为文件的名字。这样就把文件的整体数量控制住了,相同的两行数据就在同一号文件中。
场景二:现在给整个数值文件做一个正序的全排序。
– 思路一:预先设定一些文件,每个文件设定一个存储范围。最后形成了若干文件,这些文件的特点是区间有序,但是内部无序。
– 思路二:每次拿出一批数据来排序,再拿再排。这些小文件的特点是内部有序,但是区间无序。再采用归并算法来对数据进行合并。(二次IO解决)
以上都是单机解决大数据的基本思路。
02 集群
- 把文件做切割,化整为零;
- 并行操作;
每台服务器做的事情和单机处理一样,求hashcode,再对其求模。
当相同两行不在同一个文件上,需要做的就是数据的迁移。迁移的目的是让两个相同行放在同一个服务器上,迁移的原则是:让每台服务器处理相同编号的文件。
最主要的是:每个人处理的量不大,而且是在同时做这件事。
问题1:数据迁移的网络IO传输;问题二:把完整的文件做切割也比较耗时。
迁移的目的是对数据做运算,移动程序移动到数据中间。
分布式集群要做一个详细。
HDFS:如何切割成组;
03 存储和架构模型
Hadoop-HDFS
HDFS的作用是:大数据如何把数据存储在集群中。分布式:化整为零,完整的一个文件切割之后以块的形式散列在整个服务器集群的各个节点上。每个块允许创建副本,同一文件块的大小一致,不同文件的块大小可以不一致。
把一个完整的文件切割为小的文件存储在不同的服务器节点之上。其存储依赖一定的规则,规则就是存储模型的设计基础。计算机底层读取的是0101的数据,把文件想象为字节数组,把字节数组切分为不同的块,放在不同的服务器之上。
假定文件是100个字节,要把其分成不同的块,放在不同的服务器上。
一个块称为block,block块可以散列在节点之上来存放。假定有5台服务器,10个块可以分两个块来放,根据服务器数量来定。第二点,最终要达到负载均衡,每个服务器上的块差不多。
放置block块。
靠什么来切割文件:以字节为单位来切分。(不管是不是完整数据,都直接切,后期弥补。)
偏移量:指每一个块被切割成的每个块的起始的偏移位置,偏移量起到了索引定位的作用。
单一文件block块如果是10都是10,但是最后一个block块的大小不一定。同一个文件切割的block块大小要一致,如果不一致则定位会出现问题,且文件处理能力会受到文件大小的影响。
设置副本数:一个文件切割成了10块,实际的块数是30个(默认)。切完了准备3个相同的block块(2个副本),把每个块切出来的三个副本放在3个不同的服务器节点上。这么做的目的是为了数据安全。 对每个块设计若干个相同的块,将其放入不同的节点,这样就保证了从别的服务器恢复数据的功能。
切割成块,化整为零,横向扩展。副本来纵向扩展。
副本数超过节点数会导致两个副本在相同节点上,没有意义。
单一块大小默认128M,副本数默认为3。块的大小决定了移动到块的程序的执行时间。
如果副本数或块文件没有太多的作业来访问,可以按照默认。假定文件块会常有作业来访问,不要把所有进程都放在一个块来跑,让作业去跑相同块的别的服务器。
上传块时,一次性的规定好并且上传到节点上,之后不能修改或删除块的大小。把精力放在分布式计算,不要放在维护块的大小上。一次写入,多次读取。
架构类型-主从架构
通过一定的组织关系,从而达到对数据的维护。
主从架构:主节点管理文件的元数据信息MetaData,从节点负责执行处理具体的文件数据,即一个个的块文件。
主节点的每一个角色用来维护元数据信息的完整性,从节点的角色用来维护本节点的资源信息,及具体执行放在本节点之上的数据块的运算模式。
主节点:NameNode,从节点:DataNode。
元数据信息:包括块的大小,块偏移量,块的权限。元数据信息指的是切割成块的块属性信息,用metadata来维护。
想存又想快速的找:让一个人当管理者来进行记录。有一个列表用来表示对应文件存储的位置。
NameNode的作用是维护存放在集群中块文件的元数据信息。 从节点用来维护管理自己的块的信息,每个从节点之上都会有datanode的角色,而每个datanode只负责维护管理放在自己节点之上的块文件。
NameNode和DataNode之间,联系比较紧密。两者之间要保持心跳,每隔一段时间要相互ping下。需要确定每个datanode管理哪些block块。由datanode向namenode提供块的列表。(主动提供汇报)
为甚么不是问,而是datanode要汇报?–保持心跳,即能完成相应的工作。
HdfsClient:客户端和集群的关系,访问集群或把数据存入集群,客户端的交接对象是NameNode。
借助本地文件系统在存储,借助本地服务器,把其放在某个目录之下。
04 持久化
从NameNode获知数据所在的节点,然后客户端可以直接与数据所在的节点完成交互。
HDFS架构:
hdfs 客户端:发布对hdfs存储架构的发布指令,首先与nameNode进行交互,因为namenode存储有保存的元数据信息。NameNode和DataNode有虚线连接,表示主节点与从节点间保持通讯,NameNode会掌控每个DataNode上数据的信息,也掌控整个资源信息。
客户端与NameNode进行交互之后,接下来直接与DataNode进行交互。
Secondary NameNode 到2.0版本后作用就不大了,一个块设置三个副本设置在底层。
一个50G的文件放在下面的集群中,每个集群不见得能存下50G,因此第一步是把文件先做一个切割成一堆的64M大小的block块,一个块所有的副本放在node的节点列表上。
内存存储的持久化:
为什么需要持久化:和NameNode的存储模型有很大关系。
N ameNode是基于内存存储,NameNode主节点只维护元数据信息,不会和磁盘发生交换。
什么情况下会发生交换–关系型数据库会经常发生内存与磁盘的双向交换,sql语句把磁盘中的表数据加到内存中,加到内存中可能会进行修改,在内存中改完后,再写回到表中,这是一次交互。与磁盘的内存交互的必要性体现在:假定内存中的数据加载过多,已经满了,溢写到磁盘之上,腾出数据来在内存中存新的数据。
如果溢写的数据写到磁盘之后,客户端有需求需要来查询这些数据,需要不断的让内存和磁盘进行交互。
但是Hadoop元数据的处理方式上,它是不与磁盘发生交互的。意味着所有处理都在内存中完成,目的就是快。(磁盘处理和内存处理差着量级)
所有DataNode块的信息都要交给NameNode来进行维护,要求它处理事情很快,因此纯内存来操作。带来的风险就是只和内存交互的数据,特点都是需要做一个持久化操作,因为内存数据掉电易失。
持久化:把内存中的数据存到磁盘中永久保存。(单向)
持久化后恢复数据时,会发生作用。
为什么不存block的位置信息?
如果有个块坏了,就提供了失效信息。
所以进行交互时,由DataNode主动向NameNode进行汇报。
总结:block块的信息不提交到磁盘文件来存储。
NameNode持久化的作用和持久化的特点。
NameNode持久化的操作有几种方式:
持久化–把内存当中的元数据信息以文件的形式永久的保存在磁盘之上。
fsimage就是做镜像快照,保留了当时在停幅之前,整个数据库内存的一个状态,保留到磁盘文件中。以文件的形式存储到磁盘,存储磁盘文件是什么性质呢?序列化就是把文件对象给转化为二进制的字节码文件,转化的好处就是兼容性,为跨平台跨节点跨跨文件使用。反序列化就是把fsimage的二进制变为文件。恢复比较快,序列化慢。
edits是日志编辑工作:把客户端对服务器的所有主节点的每一条指令操作都写入到操作日志这个文件中。写完之后怎么进行恢复?log文件都是指令,恢复的时候就是再执行一遍。那么恢复的时候就比较慢。
总结:持久化两种方式–fsimage镜像快照(写的慢,恢复快),edits日志编辑(写的快,恢复慢)。
镜像快照为什么叫时点快照?
按照时点来定时完成。(时时刻刻生成的话会有内存与磁盘交互的问题。)
如何两者配合完成恢复?
思路:考虑这些文件产生的时间段,什么时候产生fsimage文件以及,edits log的文件。
第一次产生fsimage时是在整个文件系统格式化时(格式化的目的就是为了生成fsimage文件),在format过程中,会产生第一个fsimage文件,此时fsimage文件里没有东西。
Hadoop集群启动时,会有自己的一套流程, 集群跑起来后先去读fsimage文件,同时会产生edits log文件(都为空)。edits和fsimage会做一个合并的工作,合并成一个新的fsimage,这个fsimage无论启动多少次,都不会消失了。而editslog会不断的进行增长。
当editslog太大时,利用fsimage的文件恢复快的性能,以它做基础作为恢复,就会产生一个重新合并的工作。
Hadoop恢复时以fsimage为基础,将fsimage和edits做合并工作,怎么来做合并?谁又来作为合并的角色呢?
引入:SecondaryNameNode(SNN)–负责合并
停服后,文件恢复读取的顺序:
思考:为甚么Hadoop1.0会单独找一个Secondary的节点来完成呢?
因为本身NameNode的工作已经很多了,一旦出了问题,合并还会失败。
什么情况下会触发合并,默认的情况是是两种条件:时间角度和数据量的角度。
Secondary叫做主节点的备吗?
不,只做合并。没起到备的作用。
从节点上的守护进程,从节点上也会维护一个元数据信息的文件。元数据信息和本节点上产生的block块产生直接连接关系的。元数据最主要的数据是个md5文件。(每一个块对应一个md5文件)
md5的验证值代表了当前上传文件块的完整性,假定需要下载文件块,还要对文件做验证。
为什么要等这么长时间?
单节点数据比较多,不能随便删。
4. 读写流程
高容错性:通过多个节点的副本数来维护,当有一个节点挂断时,可以从其他的节点来读取多余的副本。副本丢失后,会有一个自动的恢复机制。恢复机制就是在数据丢失后,自动的完成一个拷贝的工作。从已经存在的良好的节点上,把副本拷贝回去。这个涉及到hadoop副本的管理策略,保障了容错性。
适合批处理:移动的是计算而非数据,尽量规避数据传输,而是讲计算框架移动到数据上,来进行本地化的操作,通过block块来引导确认在哪个节点上。
Hadoop的每一个block块,为了做到数据安全性,会生成若干个副本,分别散列在不同的节点之上。副本放置策略解决就是副本的节点怎么选出来的问题。
客户端恰巧在集群服务器上,通过副本来上传集群。
核心流程是分布式文件存储系统的核心流程,有写流程和读流程:
写流程-- 如何把数据切成块,上传到不同的节点之上,这个过程怎么完成;
读流程–如何从节点中不同的服务器读取不同的块信息。
写流程:
Hadoop的clint客户端是完成相关作业的一个很重要的角色。
第一步:分布式文件系统对象,体现在java中就是java的一个类。Distributed FileSystem在写的时候注意:文件通过一个节点向另一个节点传输,网络传输数据用IO流来传输。通过分布式文件系统对象,来创建一个流:输出流,面向程序叫输入,程序向外是输出流。
(输入流和输出流,字节流和字符流,包装流和基本流)
在写的时候没有直接和DataNode联系,先通过namenode。
NameNode 通过元数据信息以及文件的列表,还会创建一个路径,路径指向其要存储的文件位置。
每个块有三个副本,那么上传一个块有三个副本要存,写的时候:1.和三个节点的第一个节点产生通讯联系;2. 把一个块切割成若干小的数据块,像管道一样进行存储;流式传输节省了时间。
确认机制只发生在DataNode和第一个DataNode之间,传递的只是第一个块。
读流程:
一个块可能在三个节点之上,但是三个快的内容是一样的。要选择读其中最近的一个块。
5. 伪分布式
第三句话的含义:比如现在通过客户端上传一个文件到hdfs分布式系统文件中,这个需要一定的过程。在这个过程中,看不到这个文件,直到把文件上传完毕后,才代之以真正的数据文件。
datanode村的是文件块;
伪分布式:SN,DN,NN角色放在同一台服务器。
密钥文件的作用:提供三个节点,三个节点各跑一个进程。每个角色是一个进程, 如果是全分布式,需要节点数的进程都启动,需要通过在一台服务器通过脚本来掉用其他服务器。这就涉及到了从一台服务器登录其他服务器,这就是免密钥文件的作用。
官网文档需要装两个软件:java的jdk和ssh免密钥文件。
谁生成公钥,谁做管理节点,谁生成公钥。
配置文件规定了块的大小,
加了home的环境变量设置:在启动集群时,不设置的话会默认找本地java的路径。
core-site.xml规定的是主角色进程的配置信息,hdfs-site.xml是从节点。
slaves规定了从节点的配置信息;
如果不做hadoop.tmp.dir
的配置的话,数据就会放在tmp的临时目录下进行存储;
集群的唯一标识号在format阶段产生,format阶段产生:fsiimage,镜像文件,当前集群id。
集群id是给整个集群中所有角色共享的,namenode有这个集群id,datanode,secondnode都有这个集群id。
每次可视化完当前节点的id就变了。
思考题:
如果不幸format了好几遍,该如何来解决这个问题?
伪分布式搭建
- 安装jdk、配置环境变量,测试;
2.免秘钥
cd
到root目录,看隐藏文件, .ssh文件。
ssh-keygen -t dsa -P ‘’ -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
id_dsa.pub是真正得密钥,即公钥。谁做管理节点,谁生成公钥文件。
多了一个authorized_keys,即表示操作完成。
一定要用别名来操作hadoop集群。
- 解压/安装hadoop
真正运行集群时的配置文件是在etc的目录下面,系统级别的可执行脚本在sbin目录下。
在任意目录下都可以运行hadoop集群,那么需要做的是:配置hadoop环境变量。
环境变量路径需要追加两个:bin和sbin;
4. 进行每个配置文件的配置
hadoop集群在启动时,只会访问etc下的hadoop目录。
Hadoop的第二次JAVA_HOME 环境变量配置
先做一个javahome的环境变量设置,在启动集群时,会默认找到local的java启动,需要在某些文件告诉这个路径在哪,否则会报jvm not found错误。
hadoop-env.sh
echo $JAVA_HOME
vim hadoop-env.sh
vim map-env.sh
vim yarn-env.sh
文件在hadoop的etc目录下的hadoop目录下。
修改配置文件
core-site.xml规定主角色进程的配置信息:NameNode
vi core-site.xml
<property>
<name>fs.defaultFS</name>
<value>hdfs://node06:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/sxt/hadoop/local</value>
</property>
配置hdfs-site.xml:配置从节点的配置信息,副本数,对于伪分布式,一个块就一个副本就够了。NameNode有了,副本数有了,DataNode和SecondaryNode还没有。
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
slaves规定的是从节点的配置信息,伪分布式的主从节点都放在一个节点之上,这里改为主机名即可:
配置sencondarynamenode:
在hdfs-site.xml配置secondarynamenode:
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node06:50090</value>
</property>
打开core-sit文件,在配置文件中进行修改:
目的是把这个路径重新进行指向。
格式化:
生成fsi-image的镜像文件。
每一个hadoop集群在启动时,都会生成一个唯一标识号,format阶段产生三个重要内容:fsimage,镜像文件,当前集群的id。集群id是给集群的所有角色共享的。如果集群id不同,则启动集群时会出现有的角色跑不起来的情况。
格式化多次不一定是好事。
格式化hdfs
hdfs namenode -format (只能格式化一次,再次启动集群不要执行)
启动集群
start-dfs.sh
角色进程查看:jps
帮助: hdfs
hdfs dfs
可以看到hadoop启动成功。
完成上传文件操作:
上传文件由客户端和NameNode进行交互
先创建路径path;
上传文件:
文件上传后它是以什么状态存在的?
- 以块存储,存储路径的data目录下:切成两个块,每个块的大小是128MB;