您的位置 首页 java

史爱武:学习分布式存储技术HDFS

来源微信公众号:计算机大学生

关于 分布式存储 实际上并没有一个明确的定义,甚至名称上也没有一个统一的说法,经常称作分布式数据存储DDS(Distributed Data Store) 或者分布式存储系统DSS( Distributed Storage System)。

维基百科 给出的定义是:分布式存储是一种计算机网络,它通常以数据复制的方式将信息存储在多个节点中。

百度百科 给出的定义是:分布式存储系统,是将数据分散存储在多台独立的设备上。分布式网络存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息。

尽管分布式存储的定义并不完全相同,但有一点是一致的: 就是分布式存储将数据分散放置在多个节点中,节点通过网络互连提供存储服务。

这一点也是与传统集中式存储的关键区别,集中式存储是采用数据集中放置的方式。

传统的 网络存储 系统采用集中的存储服务器存放所有数据,存储服务器成为系统性能的瓶颈,也是 单点故障 (可靠性)和拒绝服务攻击DoS(安全性)的焦点,不能满足大规模存储应用的需要。

分布式存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,不但提高了系统的可靠性、可用性和存取效率,还易于扩展。

为了满足不同的应用场景和访问需求,分布式存储系统往往分为块存储、文件存储和 对象存储 三种接口形式。当然,一个分布式存储系统也可以同时提供这三种形式的服务。

比如, Ceph 是一个可靠、负载均衡、自动恢复的分布式存储系统,根据场景划分可以将Ceph分为三大块,分别是对象存储、块存储和文件系统服务。

块存储、文件存储和对象存储

(1) 块存储 可以认为是提供裸硬盘的服务,最多是将底层的物理硬盘封装,然后以逻辑卷的方式呈现给上层应用,也就是在硬盘分区上加一层逻辑卷。

常见的 块存储 技术分为两种,一种是本地块存储,如直连方式存储 DAS IP-SAN iSCSI )、 FC-SAN 存储区域网络等,另外一种是分布式块存储如 Sheepdog(由 NTT 的3名日本研究员开发的开源项目,主要用来为 虚拟机 提供块设备)、OpenStack Cinder、Ceph RDB、AWS的EBS,青云的云硬盘和 阿里云 的盘古系统等。

块存储最明显的特征就是不能被操作系统直接读写,操作系统还需要对挂载的裸硬盘进行分区、格式化为指定的文件系统(Ext3、 Ext4 NTFS 等),然后才能访问。这和平常使用的台式机(笔记本)的内置硬盘没什么两样,IO读写快,但不利于扩展和共享。

简单来说,块存储就是提供了对外的块设备存储的接口。这种接口通常是以QEMU驱动器或者内核模块的方式,需要实现QEMU提供的块驱动器接口或者 Linux 的块设备接口。

用户需要把块存储卷附加到虚拟机(或者主机)上后才可以与其交互。这些卷都是持久的,用户可以从运行的机器上解除块存储卷或者重新附加这些卷,而块存储卷上的数据保持完整不变。

OpenStack 中的虚拟机实例需要挂载存储卷,在存储卷中实现数据的持久化,否则虚拟机一关机,操作的数据(文件)都会丢失的。 Cinder是OpenStack中提供块存储服务的组件,就是管理所有块存储设备,为虚拟机提供所需要的存储卷服务,从虚拟机实例的角度来看,挂载的每一个卷都是一块硬盘。

(2) 文件存储 是我们最熟悉的存储方式,也就是文件系统存储,主要操作对象是文件和文件夹。Ext3、Ext4、NTFS是本地文件存储; NFS CIFS 是网络文件存储(NAS存储),通常都是支持 POSIX 访问接口。

分布式文件存储跟传统的文件系统(如Ext4)是一个类型的,但区别在于分布式存储提供了并行化的能力,常见分布式文件存储系统有Glusterfs、 FastDFS 、CephFS等,但是有时候又会把 GFS hdfs 这种放宽了POSIX接口的也归为分布式文件系统一类。

(3) 对象存储 可以理解为把文件分解成一个个对象进行存储,简单说就是存储文件会附加一段元数据,查询时寻找元数据然后定位到文件即可。

块存储读写快,不利于共享,文件存储读写慢,有利于共享。能不能有一个读写快,又利于共享的分布式存储系统呢?于是就有了对象存储。

之所以出现了对象存储这种东西,是为了克服块存储与文件存储各自的缺点,发挥他们各自的优点。对象存储可以说结合了文件存储和块存储的优点,是存储的发展方向。

常见的对象存储有 Ceph 的RADOS、OpenStack的 Swift 、AWS S3等,也就是通常意义的键值存储,其访问接口基本都是Restful API, 也就是简单的GET、PUT、 DEL 和其他扩展命令。

综上所述,块存储就是最接近存储介质的接口,也就是封装最少,或者根本没有封装。文件存储和对象存储都是对块存储的封装,可以简单认为,对象存储就是不分层次的文件存储,或者说,文件存储是把对象存储进一步的层次化封装而成。

分布式对象存储和分布式文件系统的表面区别是访问接口的不同: 对象存储支持的是Restful API接口,文件系统提供的POSIX兼容的文件操作接口 。但最实质的区别在于:文件系统 文件组织方式 为目录树,而对象存储采用的则是扁平化的组织方式(根据键,找到值),所以对象存储一般不支持追加写和更新,面向的是一次写入,多次读取的需求场景。

分布式文件存储系统:HDFS

分布式文件系统 是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。分布式文件系统的设计一般都是基于主从模式。

Hadoop 实现了一个分布式文件系统HDFS。HDFS有着高容错性的特点,并且设计用来部署在低廉的硬件上,提供高传输率来访问应用程序的数据,适合那些有着超大数据集的应用程序。HDFS放宽了POSIX接口要求,可以流的形式访问文件系统中的数据。

一、HDFS的工作机制和原理

HDFS采用了主从(Master/Slave)结构模型,一个HDFS集群是由一个名字节点(Namenode)和若干个数据节点(Datanode)组成的。

名字节点(Namenode)和数据节点(Datanode)

名字节点作为主服务器,提供元数据服务,管理文件系统的命名空间和客户端对文件的访问操作;数据节点管理存储的真正数据。HDFS对外开放文件命名空间并允许用户数据以文件形式存储。

HDFS 内部的所有通信都基于标准的 TCP/IP 协议。存储在 HDFS 中的文件被分成块,然后将这些块复制到多个数据节点。块的大小(默认大小在Hadoop2.x版本中是128M,之前的版本中是64M)和复制的块数量在创建文件时由客户端决定。应用程序可以设置HDFS保存的文件的副本数目(文件的副本系数),这个信息也是由名字节点保存的。

名字节点用来操作文件命名空间的文件或目录,任何对文件系统名字空间或属性的修改都将被名字节点记录下来,如打开、关闭、重命名等等,同时确定块与数据节点的映射。数据节点负责来自客户的读写请求,同时还要执行块的创建、删除和来自名字节点的块复制指令。

HDFS是用 Java 编写的,任何支持Java的机器都可以运行名字节点或数据节点。通常情况下,名字节点和数据节点都是运行在普通的Linux机器上。典型的部署是由一个专门的Linux机器来运行名字节点软件,集群中的其他每台Linux机器运行一个数据节点实例。当然,一台机器上也可以运行多个数据节点的实例,但是实际部署不会采用这种情况。

HDFS支持传统的层次型文件组织结构,文件系统的层次结构和大多数现有的文件系统类似。用户或者应用程序可以创建目录,可以创建、删除、移动或重命名文件,然后将文件保存在这些目录里。当前,HDFS不支持用户 磁盘配额 和访问权限控制,也不支持硬链接和软链接,未来也许会实现这些特性。

数据复制

HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的。

为了容错,文件的所有数据块都会有副本。每个文件的数据块大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目,副本系数可以在文件创建的时候指定,也可以在之后改变。

Namenode 节点全权管理数据块的复制,它周期性地从集群中的每个Datanode节点接收心跳信号和块状态报告。接收到心跳信号意味着该Datanode节点工作正常,块状态报告包含了该Datanode节点上所有数据块的列表。

副本的存放是HDFS可靠性和性能的关键。HDFS采用一种称为机架感知(Rack-Aware)的策略来存放副本,从而改进数据的可靠性、可用性和网络带宽的利用率。优化的副本存放策略是HDFS区分于其他大部分分布式文件系统的重要特性。

大型HDFS分布式文件系统一般运行在跨越多个机架的服务器组成的集群上,不同机架上的两台服务器之间的通讯需要经过 交换机 。在大多数情况下,同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。

一个简单但没有优化的“机架感知”策略就是将副本存放在不同的机架上。当机架发生故障时,可以有效防止数据的丢失;读数据的时候,允许充分利用多个机架的带宽。

这种策略设置可以将副本均匀分布在集群中,有利于当组件失效情况下的负载均衡。但是,在执行写操作的时候,这种策略需要传输数据块到多个机架,大大增加了写的代价。

在大多数情况下,HDFS优化的副本(如副本系数是3)存放策略是这样工作的: 将一个副本存放在本地机架的一个节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。

这种副本存放策略减少了机架间的数据传输,也就提高了写操作的效率。机架的错误远远比节点的错误少,所以这个策略不会影响到数据的可靠性和可用性。同时,因为数据块只放在两个(不是三个)不同的机架上,所以此策略减少了读取数据时需要的网络传输总带宽。

在这种策略下,副本并不是均匀分布在不同的机架上。三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。

为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本。如果在读取程序的同一个机架上有一个副本,那么就读取该副本。如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本。

总结来说,理解分布式文件系统HDFS的工作机制和原理,重点是要理解下面的一些概念和流程:

l HDFS集群分为Namenode节点和Datanode节点,Namenode负责管理整个文件系统的元数据,Datanode 负责管理用户的文件数据块。

l HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过访问Namenode节点开始的。

l HDFS中的文件在物理上是分块存储(Block),文件会按照固定的大小切成若干块后分布式存储在若干台Datanode节点上,块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,之前的版本中是64M。

l 文件的各个分块block的存储管理由Datanode节点承担,Datnode节点是HDFS集群的总节点。每一块都可以在多个Datanode上存储多个副本(副本数量也可以通过参数设置dfs.replication,默认是3)。

l HDFS文件系统会给客户端提供一个统一的抽象目录结构,目录结构及文件分块位置信息(元数据)的管理由Namenode节点承担,Namenode是HDFS集群主节点,负责维护整个HDFS文件系统的目录树,以及每一个路径(文件)所对应的数据块信息(BlockID及所在的Datanode服务器)。

l Datanode节点定期向Namenode汇报该节点上保存的文件block块信息,而Namenode则会负责保持文件的副本数量。

HDFS写数据流程

客户端要向HDFS写数据,首先要跟Namenode节点通信以确认可以写文件并获得接收文件block块的Datanode节点,然后客户端按顺序将文件逐个block传递给相应Datanode节点,并由接收到block块的Datanode节点负责向其他Datanode复制block的副本。

HDFS写数据的流程大致如下:

1) 客户端向Namenode节点发送上传文件请求,Namenode节点对要上传目录和文件进行检查,判断是否可以上传,并向客户端返回检查结果。

2) 客户端得到上传文件的允许后读取客户端配置,如果没有指定配置则会读取默认配置(例如副本数和块大小默认为3和128M),并向Namenode节点请求上传一个数据块。

3) Namenode节点会根据客户端的配置来查询Datanode节点信息,如果使用默认配置,那么最终结果会返回同一个机架的两个Datanode节点和另一个机架的一个Datanode节点,这称为“机架感知”策略。

4) 客户端在开始传输数据块之前会把数据缓存在本地,当缓存大小超过了一个数据块的大小,客户端就会从Namenode节点获取要上传的Datanode节点列表。之后会在客户端和第一个Datanode节点建立连接,开始流式的传输数据。这个Datanode节点接收数据然后写入本地存储,同时会把这些数据传输到第二个Datanode节点,第二个Datanode节点同时传输给第三个Datanode节点,依次类推。这样逐级调用和返回之后,待这个数据块传输完成,客户端会告诉Namenode节点数据块传输完成,这时候Namenode节点才会更新元数据信息,记录操作日志。

5) 第一个数据块传输完成后,使用同样的方式传输后面的数据块直到整个文件上传完成。

HDFS读数据的流程

客户端将要读取的文件路径发送给Namenode节点,Namenode节点获取文件的元数据信息(主要是block的存放位置信息)返回给客户端。客户端根据返回的信息找到相应Datanode节点,逐个获取文件的block,并在客户端本地进行数据追加合并从而获得整个文件。

HDFS读数据的流程如下:

1) 客户端向Namenode节点请求读取文件数据。

2) Namenode节点检查文件是否存在,如果存在则获取文件的元数据信息,也就是blockID以及对应的Datanode节点列表。

3) 客户端收到元数据信息后,选取一个网络距离最近的Datanode节点,客户端与Datanode节点建立Socket连接,传输对应的数据块。

4) 客户端收到数据块,首先要校检block块是否损坏,如果损坏,客户端会选取另外的Datanode节点读取该数据块。

5) 客户端收到数据块缓存到本地,依次传输剩下的数据块,然后写入文件,直到整个文件合并完成。

二、访问方式

HDFS分布式文件系统给用户提供了多种访问方式。用户可以通过命令行方式、HTTP浏览器方式、Java API接口访问,也可以通过C语言的封装API访问。

HDFS以文件和目录的形式组织用户数据。Hadoop支持很多 Shell 命令,比如hadoop fs、 hadoop dfs和hdfs dfs都是HDFS最常用的Shell命令,用来查看HDFS文件系统的目录结构、上传和下载文件、创建文件等。

这三个命令既有联系有又区别:hadoop fs适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统;hadoop dfs只能适用于HDFS文件系统;hdfs dfs和hadoop dfs命令的作用一样,也只能适用于HDFS文件系统。

命令的语法和用户熟悉的其他shell(例如 bash , csh)工具类似。如创建一个名为/foodir的目录,上述三个命令之一是:bin/Hadoop dfs -mkdir /foodir。这些命令行指令可以用在那些通过 脚本语言 和HDFS文件系统交互的应用程序上。

典型的HDFS安装环境下,会在一个可配置的 TCP端口 开启一个 Web服务器 ,用户可以用浏览器来浏览HDFS的名字空间和查看文件的内容。Namenode节点和Datanode节点各自启动了一个内置的Web服务器,显示了集群当前的基本状态和信息。

在默认配置下,Namenode节点的地址是。这个页面列出了集群里的所有Datanode和集群的基本状态。这个Web接口也可以用来浏览整个文件系统(使用Namenode首页上的”Browse the file system”链接)。

除了用HDFS 命令行、Web等方式来访问HDFS之外,Hadoop还提供了以 Java API 的方式来操作HDFS分布式文件系统。实际应用场景中,基本上都是基于这些API来开发客户端应用访问HDFS。

比如,要利用HDFS分布式文件系统来构建一个类百度云盘一样的系统,可以基于HDFS的Java API来开发个性化的云盘客户端。具体的Java API使用方法,在HDFS的官方网站上有详细的开发文档,此处不作深入描述。

文章来源:智云一二三科技

文章标题:史爱武:学习分布式存储技术HDFS

文章地址:https://www.zhihuclub.com/185823.shtml

关于作者: 智云科技

热门文章

网站地图