Apache Hadoop(3)---可靠的分布式存储HDFS

栏目: 服务器 · 发布时间: 5年前

内容简介:GFS在MapReduce框架之间被提出,毕竟首先要解决大数据存储,然后才能开始考虑在此之上的处理问题。虽然说商业级的硬盘故障率较低,硬盘容量也越做越大,但是单盘的容量毕竟有限,而且读写速度也提升的相对没有那么快,摩尔定律也有放缓甚至失效的那一天。在当前网速动辄万兆的对比下,硬盘读写速度才不过百兆或勉强超过千兆。对于一个大容量硬盘。即便是假设它在服务周期内不会出现故障,全盘读取也要耗费数小时以上的时间。在单盘难以容纳海量数据的情况下采用分布式存储的形式,即将数据分割存储到不同的硬盘上。不管工艺多么好,总会有

GFS在MapReduce框架之间被提出,毕竟首先要解决大数据存储,然后才能开始考虑在此之上的处理问题。虽然说商业级的硬盘故障率较低,硬盘容量也越做越大,但是单盘的容量毕竟有限,而且读写速度也提升的相对没有那么快,摩尔定律也有放缓甚至失效的那一天。在当前网速动辄万兆的对比下,硬盘读写速度才不过百兆或勉强超过千兆。对于一个大容量硬盘。即便是假设它在服务周期内不会出现故障,全盘读取也要耗费数小时以上的时间。

在单盘难以容纳海量数据的情况下采用分布式存储的形式,即将数据分割存储到不同的硬盘上。不管工艺多么好,总会有残次品的存在,况且硬盘的寿命不固定,面对大量的硬盘,偶尔出现一两块坏盘是非常常见的。尤其是硬盘过保了还坚持超期服役,那这个故障率更会大大提升,一块盘坏了,那么上面的数据就全丢了,而修复的价格不菲。

尽管可以通过设置RAID来减少单盘故障带来的影响,但是RAID并没有解决大数据的存储问题,毕竟你不能把所有的硬盘都接到一台机器上,而且万一这台服务器网络故障、断电了,真个存储将处于不可用的状态,在线服务也会大受影响。你看阿里的技术够厉害了吧,还不是敌不过挖掘机的一铲子?

化零为整

把数据分布在不同的硬盘上这个主意不难想到,但是面对频发的故障,如何保证数据的持久性、可用性、负载均衡,乃至于后续的弹性扩容并没有那么容易。

首先对于硬盘故障,我们不能期望通过硬盘修复来找回数据,修复的速度也没有那么迅速。面对硬盘故障,唯一可以做的就是通过冗余,即便丢失了部分数据但是还能通过其他部分补充回来。一种做法是冗余码,把文件分成N块,然后保证在最多丢失M块的情况下还能完整恢复原文件,冗余度越高,容错率越强,当然了额外占用的硬盘容量也会越高,通过冗余码的方式在恢复时也需要额外的计算资源。

HDFS 采取的是另外一种形式,即多副本,将每一个文件复制多份并保存到多个节点上,这样即便是一个节点当机或硬盘故障,还能从其他节点上读取。HDFS封装了很多的底层细节,包括故障之后将丢失的副本冗余到新的节点、数据的负载均衡、弹性扩容等等。对于用户来说,对于数据的存取就像是在单机上操作一样。(当然了,需要使用HDFS的接口,虽然有相关项目把HDFS挂载到本地,但是按照HDFS的设计,速度应该会很慢,关键是HDFS不支持修改)

Block

对于一个大数据文件,它的容量可能已经大大超过了单机所能容纳的规模,这就需要分块存储。在计算机硬盘中是存在块的概念的,但是它的容量很小,按照HDFS的设计,这些块的元信息都是存储在NameNode上,太多的块会降低索引效率,而且不便于管理。考虑到大数据领域文件通常会很大,所以可以将块大小设置的很大。目前默认的块大小是128M。

但是HDFS的块只是逻辑上的,在实际存储的时候还是会按照文件块的实际大小存储,而且有可能会超过块的大小,是一种软限制。

一次写入,多次读取

HDFS主要设计用于解决OLAT即离线数据分析,这种场景下,数据基本上是一次写入多次读取,并且不会修改原有的内容,这简化了HFDS的复杂度。可以在文件末尾添加,但是不能修改原有文件。

组件

在HDFS中,主要有两种组件:namenode和datanode。分布式存储一般采用中心化或去中心化的设计,去中心化的好处在于可以通过一些哈希算法等确定文件所在节点,避免了中心节点的性能和单点故障问题,GlusterFS就采取了这种做法,但是这种做法也会带来一些问题,例如对文件遍历等效率不高。负载均衡问题,各个节点需要监测集群健康状况。

HDFS采用了中心化的形式,元数据存储在namenode节点,datanode只需要负责按照namenode要求存取文件块、监测文件块情况并定时汇报。每次请求都会先与namenode通信。

NameNode

namenode是HDFS中的中心,存储整个文件系统的元数据信息,包括文件名,拥有着,权限,等等信息。此外,还存储了每个文件的块所在的节点,由于块信息变化较快且能够根据datanode的心跳来恢复,所以为了提高效率,块信息是存储在内存中的应用,namenode启动时,会根据datanode的心跳情况来重建。

namenode中存储文件系统状态的数据结构/文件叫image。作为一个负载较高的系统,为了保证一致性等,直接在iamge上进行修改会大大降低系统的吞吐量,所以HDFS采用了写log的方式来记录事实文件修改,然后周期性合并image和editlog,其中image是状态,log是操作。

Secondary NameNode

Secondary NameNode 不是一个必需组件,它存在的意义在于接手namenode合并image和editlog,从而减轻namenode的压力。Secondary NameNode会定期从namenode拉取image和editlog,合并之后再传输回namenode。

需要注意的是,Secondary NameNode并不是namenode的热备份,namenode节点当机之后Secondary NameNode并不会接手,它只负责合并image和editlog。

DataNode

datanode是HDFS中负责数据实际存储的节点,根据namenode的分配,接受客户端数据并写入本地硬盘。在一个分布式集群中,网络故障,节点当机问题时有发生,为了不影响服务可用性,就需要尽快感知到并及时用其他节点替代。在HDFS中,是采用心跳的方式来向namenode汇报,表明当前节点依旧在线。如果namenode长时间没有收到来自datanode的心跳,就会认为这个节点故障或失效,开启启动服务程序,找到该节点还是难过存储的文件块,然后再从其他节点上复制相应的块到其他的节点上 ,保证多副本。(此外,客户端读写故障时也会将故障节点汇报给namenode)

在心跳时,datanode会将该节点中所存储的文件块发给namenode,以便跟踪文件存储情况。

读写步骤

Read

从HDFS读取文件需要经过以下步骤:

  1. 客户端请求namenode,读取某一个文件/目录
  2. namenode检查文件是否存在、用户是否拥有读取权限等验证工作
  3. 验证通过后,namenode返回一个列表,每一项对应一个block以及存储datanode节点(datanode列表按照数据本地性排序,如果block很多,会分批)
  4. 对于每一个block,客户端向第一个datanode建立连接,读取块内容。如果第一个datanode出现故障,客户端会请求下一个datanode
  5. 客户端在接收到block之后会检验文件块是否损坏(通过对比写入时校验和与读取时计算的校验和是否一致,故障则从下一个节点读取,并向namenode汇报)

Apache Hadoop(3)---可靠的分布式存储HDFS

Write

向HDFS中时,需要经过以下几个步骤:

  1. 客户端首先向namenkde发送消息,请求创建文件并分配datanode节点
  2. namenode检查用户权限,文件夹是否已经存在,并分配N个datanode节点(N是副本数,根绝数据本地性等因素排序)
  3. 为了最大限度的利用带宽,HDFS采取了串行写的方案,即客户端向第一个datanode写入文件,第一个datanode向第二个datanode写入,直到最后一个
  4. 由于涉及多个节点(且是串行写),故障率相对较高,对于每一个block,客户端会拆分成一个一个的packet,将发出去的packet添加到等待确认队列中,经过串行写之后,等待最后一个datanode发出确认包之后这个packte才算写入完毕(类似TCP中滑动窗口协议)
  5. 当该blobk写入完毕,客户端向namenode请求一个新的datanode写入列表,然后重复上述步骤
  6. 如果在写入过程中有datanode出现故障,串行写pipeline连接会被关闭,然后重新建立(去掉故障的节点),重新分配block的id(这样故障节点会在恢复后发现存储了无引用的block,从而删除),然后从确认队列中的packet开始继续传输(已经确认的packet不需要重新传输),缺失的副本会由HDFS的检测系统来自动补全
  7. 只要成功写入的datanode节点数不低于用于定义的最小副本数写入都会进行

Apache Hadoop(3)---可靠的分布式存储HDFS

高可用HA

正如前面提到的一样,HDFS是一个存在中心节点的分布式存储系统,按照HDFS的设计,少量datanode的故障不影响系统运行,但是namenode是整个系统的核心,且是单实例的,这就存在单点故障问题。在分布式系统中,解决单点故障,要么是设计成去中心,要么就是通过集群的形式用冗余来保证高可用性。

NameNode 集群

根据namenode的职责,它负责处理image、editlog和文件块信息,由于文件块信息可以通过datanode的心跳包来恢复,所以问题的关键就在于image和editlog的高可用上。首先要保证数据高可用,即节点故障的情况下,依然可以通过启动其他节点来继续服务。在高可用环境下,image和editlog存储在QJM中(它也是一个分布式存储)。

另外一个问题就是,如果做到低延迟切换。在大多数的分布式系统中,对于单点故障的解决都是采用集群的模式,而且采用主从的模式,正常情况下只有一个节点处于活跃状态,其他节点转发请求,当主节点出现故障时,从节点接手继续服务。跟很多系统一样,HDFS namenode集群的选主采用了zookeeper。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Linux Programming Interface

The Linux Programming Interface

Michael Kerrisk / No Starch Press / 2010-11-6 / GBP 79.99

The Linux Programming Interface describes the Linux API (application programming interface)-the system calls, library functions, and other low-level interfaces that are used, directly or indirectly, b......一起来看看 《The Linux Programming Interface》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具