IT技术问答
联系方式
您现在的位置:主页 > IT技术问答 > 内容

用大白话通知你小白都能看懂的Hadoop架构原理

发布时间:2018-12-07 编辑:admin

Hadoop 是现在大数据范畴最干流的一套技能体系,包含了多种技能,例如 HDFS(散布式文件体系),YARN(散布式资源调度体系),MapReduce(散布式核算体系)等等。

有些朋友或许听说过 Hadoop,可是却不太清楚它到底是个什么东西,这篇文章就用大白话给各位论述一下。

假定你现在公司里的数据都是放在 MySQL 里的,那么就悉数放在一台数据库效劳器上,我们就假定这台效劳器的磁盘空间有 2T 吧,我们先看下面这张图。

现在问题来了,你不断的往这台效劳器的 MySQL 里放数据,成果数据量越来越大了,超过了 2T 的巨细了,现在咋办?

你说,我能够搞多台 MySQL 数据库效劳器,分库分表啊!每台效劳器放一部分数据不就得了。如上图所示!

好,没问题,那我们搞 3 台数据库效劳器,3 个 MySQL 实例,然后每台效劳器都能够 2T 的数据。

现在我问你一个问题,所谓的大数据是在干什么?我们来说一下大数据最初级的一个运用场景。

假定你有一个电商网站,要把这个电商网站里一切的用户在页面和 App 上的点击、购买、阅读的行为日志都寄存起来剖析。

你现在把这些数据全都放在了 3 台 MySQL 效劳器上,数据量很大,但仍是牵强能够放的下。

某天早上,你的 Boss 来了。要看一张报表,比方要看每天网站的 X 目标、Y 目标、Z 目标,等等,二三十个数据目标。

好了,兄弟,现在你测验去从那些点击、购买、阅读的日志里,经过写一个 SQL 来剖分出那二三十个目标试试看?

我跟你打赌,你必定会写出来一个几百行起步,乃至上千行的超级杂乱大 SQL。这个 SQL,你觉得他能运转在分库分表后的 3 台 MySQL 效劳器上么?

假如你觉得能够的话,那你必定是不太了解 MySQL 分库分表后有多坑,几百行的大 SQL 跨库 Join,各种杂乱的核算,底子不现实。

所以说,大数据的存储和核算压根儿不是靠 MySQL 来搞的,因而 Hadoop、Spark 等大数据技能体系才应运而生。

本质上,Hadoop、Spark 等大数据技能,其实就是一系列的散布式体系。比方 Hadoop 中的 HDFS,就是大数据技能体系中的中心柱石,担任散布式存储数据,这是啥意思?别急,持续往下看。

HDFS 全称是 Hadoop Distributed File System,是 Hadoop 的散布式文件体系。

它由许多机器组成,每台机器上运转一个 DataNode 进程,担任办理一部分数据。

然后有一台机器上运转了 NameNode 进程,NameNode 大致能够认为是担任办理整个 HDFS 集群的这么一个进程,它里边存储了 HDFS 集群的一切元数据。

然后有许多台机器,每台机器存储一部分数据!好,HDFS 现在能够很好的存储和办理许多的数据了。

这时分你必定会有疑问:MySQL 效劳器不也是这样的吗?你要是这样想,那就大错特错了。

这个工作不是你想的那么简略的,HDFS 天然就是散布式的技能,所以你上传许多数据,存储数据,办理数据,天然就能够用 HDFS 来做。

假如你硬要根据 MySQL 分库分表这个事儿,会苦楚许多倍,由于 MySQL 并不是规划为散布式体系架构的,它在散布式数据存储这块缺少许多数据确保的机制。

好,你现在用 HDFS 散布式存储了数据,接着不就是要散布式来核算这些数据了吗?

关于散布式核算:

  • 许多公司用 Hive 写几百行的大 SQL(底层根据 MapReduce)。

  • 也有许多公司开端渐渐的用 Spark 写几百行的大 SQL(底层是 Spark Core 引擎)。

总归就是写一个大 SQL,然后拆分为许多的核算使命,放到各个机器上去,每个核算使命就担任核算一小部分数据,这就是所谓的散布式核算。

这个,必定比你针对分库分表的 MySQL 来跑几百行大 SQL 要靠谱的多。

关于上述所说的散布式存储与散布式核算,老规矩,相同给我们来一张图,大伙儿跟着图来细心捋一下整个进程。


HDFS 的 NameNode 架构原理


好了,序幕衬托完之后,进入正题。本文首要就是讨论一下 HDFS 集群中的 NameNode 的中心架构原理。

NameNode 有一个很中心的功用:办理整个 HDFS 集群的元数据,比方说文件目录树、权限的设置、副本数的设置,等等。

下面就用最典型的文件目录树的保护,来给我们举例说明,我们看看下面的图。现在有一个客户端体系要上传一个 1TB 的大文件到 HDFS 集群里。

此刻它会先跟 NameNode 通讯,说:大哥,我想创立一个新的文件,它的姓名叫“/usr/hive/warehouse/access_20180101.log”,巨细是 1TB,你看行不?

然后 NameNode 就会在自己内存的文件目录树里,在指定的目录下搞一个新的文件目标,姓名就是“access_20180101.log”。

这个文件目录树不就是 HDFS 十分中心的一块元数据,保护了 HDFS 这个散布式文件体系中,有哪些目录,有哪些文件,对不对?

可是有个问题,这个文件目录树是在 NameNode 的内存里的啊!这可坑爹了,你把重要的元数据都放在内存里,假如 NameNode 不小心宕机了可咋整?元数据不就悉数丢掉了?

可你要是每次都频频的修正磁盘文件里的元数据,功能必定是极低的啊!究竟这是许多的磁盘随机读写!

不要紧,我们来看看 HDFS 高雅的解决方案。每次内存里改完了,写一条 edits log,元数据修正的操作日志存到磁盘文件里,不修正磁盘文件内容,就是次序追加,这个功能就高多了。

每次 NameNode 重启的时分,把 edits log 里的操作日志读到内存里回放一下,不就能够恢复元数据了?

我们顺着上面的文字,把整个进程,用下面这张图跟着走一遍:

可是问题又来了,那 edits log 假如越来越大的话,岂不是每次重启都会很慢?由于要读取许多的 edits log 回放恢复元数据!

所以 HDFS 说,我能够这姿态啊,我引进一个新的磁盘文件叫做 fsimage,然后呢,再引进一个 JournalNodes 集群,以及一个 Standby NameNode(备节点)。

每次 Active NameNode(主节点)修正一次元数据都会生成一条 edits log,除了写入本地磁盘文件,还会写入 JournalNodes 集群。

然后 Standby NameNode 就能够从 JournalNodes 集群拉取 edits log,应用到自己内存的文件目录树里,跟 Active NameNode 保持一致。

然后每隔一段时间,Standby NameNode 都把自己内存里的文件目录树写一份到磁盘上的 fsimage,这可不是日志,这是完好的一份元数据。这个操作就是所谓的 checkpoint 检查点操作。

然后把这个 fsimage 上传到 Active NameNode,接着清空掉 Active NameNode 的旧的 edits log 文件,这儿或许都有 100 万行修正日志了!

然后 Active NameNode 持续接纳修正元数据的恳求,再写入 edits log,写了一小会儿,这儿或许就几十行修正日志罢了!

假如说此刻,Active NameNode 重启了,Bingo!不要紧,只要把 Standby NameNode 传过来的 fsimage 直接读到内存里,这个 fsimage 直接就是元数据,不需要做任何额定操作,纯读取,功率很高!

然后把新的 edits log 里少数的几十行的修正日志回放到内存里就 OK 了!

这个进程的发动速度就快的多了!由于不需要回放许多上百万行的 edits log 来恢复元数据了!如下图所示。

此外,我们看看上面这张图,现在我们有俩 NameNode:

  • 一个是主节点对外供给效劳接纳恳求。

  • 其他一个纯就是接纳和同步主节点的 edits log 以及履行定时 checkpoint 的备节点。

我们有没有发现!他们俩内存里的元数据几乎是如出一辙的啊!所以呢,假如 Active NameNode 挂了,是不是能够立马切换成 Standby NameNode 对外供给效劳?

这不就是所谓的 NameNode 主备高可用毛病搬运机制么!接下来我们再想想,HDFS 客户端在 NameNode 内存里的文件目录树,新加了一个文件。

可是这个时分,人家要把数据上传到多台 DataNode 机器上去啊,这可是一个 1TB 的大文件!咋传呢?

很简略,把 1TB 的大文件拆成 N 个 block,每个 block 是 128MB。1TB = 1024GB = 1048576MB,一个 block 是 128MB,那么就是对应着 8192 个 block。

这些 block 会散布在不同的机器上办理着,比方说一共有 100 台机器组成的集群,那么每台机器上放 80 个左右的 block 就 OK 了。

可是问题又来了,那假如这个时分 1 台机器宕机了,不就导致 80 个 block 丢掉了?

也就是说上传上去的 1TB 的大文件,会丢掉一小部分数据啊。不要紧!HDFS 都考虑好了!

它会默认给每个 block 搞 3 个副本,如出一辙的副本,分放在不同的机器上,假如一台机器宕机了,同一个 block 还有其他两个副本在其他机器上呢!

大伙儿看看下面这张图。每个 block 都在不同的机器上有 3 个副本,任何一台机器宕机都没事!还能够从其他的机器上拿到那个 block。

这下子,你往 HDFS 上传一个 1TB 的大文件,能够无忧无虑了吧!

OK,上面就是大白话加上一系列手绘图,给我们先聊聊小白都能听懂的 Hadoop 的根本架构原理。

大规模集群下 Hadoop NameNode 怎么承载每秒上千次的高并发拜访

上面我们现已开端给我们解说了 Hadoop HDFS 的全体架构原理,信任我们都有了必定的知道和了解。

下面我们来看看,假如许多客户端对 NameNode 建议高并发(比方每秒上千次)拜访来修正元数据,此刻 NameNode 该怎么抗住?

问题源起

我们先来剖析一下,高并发恳求 NameNode 会遇到什么样的问题。

我们现在都知道了,每次恳求 NameNode 修正一条元数据(比方说恳求上传一个文件,那么就需要在内存目录树中参加一个文件),都要写一条 edits log。

包含如下两个进程:

  • 写入本地磁盘。

  • 经过网络传输给 JournalNodes 集群。

可是假如对 Java 有必定了解的同学都该知道多线程并发安全问题吧?

NameNode 在写 edits log 时的第一条准则:有必要确保每条 edits log 都有一个大局次序递加的 transactionId(简称为 txid),这样才干够标识出来一条一条的 edits log 的先后次序。

那么假如要确保每条 edits log 的 txid 都是递加的,就有必要得加锁。

每个线程修正了元数据,要写一条 edits log 的时分,都有必要按次序排队获取锁后,才干生成一个递加的 txid,代表这次要写的 edits log 的序号。

好了,那么问题来了,我们看看下面的图。假如每次都是在一个加锁的代码块里,生成 txid,然后写磁盘文件 edits log,网络恳求写入 JournalNodes 一条 edits log,会咋样?

不用说,这个必定完蛋了!NameNode 自身用多线程接纳多个客户端发送过来的并发的恳求,成果多个线程竟然修正完内存中的元数据之后,排着队写 edits log!

并且你要知道,写本地磁盘 + 网络传输给 JournalNodes,都是很耗时的啊!功能两大杀手:磁盘写 + 网络写!

假如 HDFS 的架构真要是这么规划的话,根本上 NameNode 能承载的每秒的并发数量就很少了,或许就每秒处理几十个并发恳求处理撑死了!

HDFS 高雅的解决方案

所以说,针对这个问题,人家 HDFS 是做了不少的优化的!

首要我们想一下,已然我们不期望每个线程写 edits log 的时分,串行化排队生成 txid + 写磁盘 + 写 JournalNode,那么是不是能够搞一个内存缓冲?

也就是说,多个线程能够快速的获取锁,生成 txid,然后快速的将 edits log 写入内存缓冲。

接着就快速的开释锁,让下一个线程持续获取锁后,生成 id + 写 edits log 进入内存缓冲。

然后接下来有一个线程能够将内存中的 edits log 刷入磁盘,可是在这个进程中,仍是持续答应其他线程将 edits log 写入内存缓冲中。

可是这儿又有一个问题了,假如针对同一块内存缓冲,一起有人写入,还一起有人读取后写磁盘,那也有问题,由于不能并发读写一块同享内存数据!

所以 HDFS 在这儿采取了 double-buffer 双缓冲机制来处理!将一块内存缓冲分红两个部分:

  • 其间一个部分能够写入。

  • 其他一个部分用于读取后写入磁盘和 JournalNodes。

我们或许感觉文字叙说不太直观,老规矩,我们来一张图,按次序给我们论述一下。

①分段加锁机制 + 内存双缓冲机制

首要各个线程顺次第一次获取锁,生成次序递加的 txid,然后将 edits log 写入内存双缓冲的区域 1,接着就立马第一次开释锁了。

趁着这个空地,后边的线程就能够再次立马第一次获取锁,然后当即写自己的 edits log 到内存缓冲。

写内存那么快,或许才耗时几十奇妙,接着就立马第一次开释锁了。所以这个并发优化必定是有作用的,我们有没有感触到?

接着各个线程竞赛第2次获取锁,有线程获取到锁之后,就看看,有没有谁在写磁盘和网络?

假如没有,好,那么这个线程是个幸运儿!直接交流双缓冲的区域 1 和区域 2,接着第2次开释锁。这个进程适当快速,内存里判别几个条件,耗时不了几微秒。

好,到这一步停止,内存缓冲现已被交流了,后边的线程能够立马快速的顺次获取锁,然后将 edits log 写入内存缓冲的区域 2,区域 1 中的数据被确定了,不能写。

怎么样,是不是又感触到了一点点多线程并发的优化?

②多线程并发吞吐量的百倍优化

接着,之前那个幸运儿线程,将内存缓冲的区域 1 中的数据读取出来(此刻没人写区域 1 了,都在写区域 2),将里边的 edtis log 都写入磁盘文件,以及经过网络写入 JournalNodes 集群。

这个进程可是很耗时的!可是不要紧啊,人家做过优化了,在写磁盘和网络的进程中,是不持有锁的!

因而后边的线程能够噼里啪啦的快速的第一次获取锁后,立马写入内存缓冲的区域 2,然后开释锁。

这个时分许多的线程都能够快速的写入内存,没有堵塞和卡顿!怎么样?并发优化的感觉感触到了没有!

③缓冲数据批量刷磁盘 + 网络的优化

那么在幸运儿线程吭哧吭哧把数据写磁盘和网络的进程中,排在后边的许多线程,快速的第一次获取锁,写内存缓冲区域 2,开释锁,之后,这些线程第2次获取到锁后会干嘛?

他们会发现有人在写磁盘啊,兄弟们!所以会当即休眠 1 秒,开释锁。

此刻许多的线程并发过来的话,都会在这儿快速的第2次获取锁,然后发现有人在写磁盘和网络,快速的开释锁,休眠。

怎么样,这个进程没有人长期的堵塞其他人吧!由于都会快速的开释锁,所以后边的线程仍是能够敏捷的第一次获取锁后写内存缓冲!

Again!并发优化的感觉感触到了没有?

并且这时,必定会有许多线程发现,如同之前那个幸运儿线程的 txid 是排在自己之后的,那么必定就把自己的 edits log 从缓冲里写入磁盘和网络了。

这些线程乃至都不会休眠等候,直接就会回来后去干其他工作了,压根儿不会卡在这儿。这儿又感触到并发的优化没有?

然后那个幸运儿线程写完磁盘和网络之后,就会唤醒之前休眠的那些线程。

那些线程会顺次排队再第2次获取锁后进入判别,咦!发现没有人在写磁盘和网络了!

然后就会再判别,有没有排在自己之后的线程现已将自己的 edtis log 写入磁盘和网络了:

  • 假如有的话,就直接回来了。

  • 没有的话,那么就成为第二个幸运儿线程,交流两块缓冲区,区域 1 和区域 2 交流一下。

  • 然后开释锁,自己开端吭哧吭哧的将区域 2 的数据写入磁盘和网络。

可是这个时分没有关系啊,后边的线程假如要写 edits log 的,仍是能够第一次获取锁后立马写内存缓冲再开释锁。以此类推。

总结

这套机制仍是挺杂乱的,触及到了分段加锁以及内存双缓冲两个机制。

经过这套机制,NameNode 确保了多个线程在高并发的修正元数据之后写 edits log 的时分,不会说一个线程一个线程的写磁盘和网络,那样功能真实太差,并发才能太弱了!

所以经过上述那套杂乱的机制,尽最大的尽力确保,一个线程能够批量的将一个缓冲中的多条 edits log 刷入磁盘和网络。

在这个绵长的吭哧吭哧的进程中,其他的线程能够快速的高并发写入 edits log 到内存缓冲里,不会堵塞其他的线程写 edits log。

所以,正是依托以上机制,最大极限优化了 NameNode 处理高并发拜访修正元数据的才能!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69900357/viewspace-2222086/,如需转载,请注明出处,否则将追查法律责任。

本文源自: 揭秘环亚娱乐骗局

上一篇:MySQL存储过程部分解释

下一篇:没有了

Copyright © 2005-2016 http://www.chickagoan.com 揭秘环亚娱乐骗局_揭秘环亚娱乐黑钱_环亚娱乐安全_网易新闻版权所有 揭秘环亚娱乐骗局_揭秘环亚娱乐黑钱_环亚娱乐安全_网易新闻