这个 , 绝对比你针对分库分表的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 。
