
大家所了解的几种分布式文件传输平台,如GFS、TFS、Swift、Ceph等等,在平台架构的设计上大同小异,在现在的知识边界内,主要从下面两点展开吧。其一,是有无中心管理节点;其二,存储节点是否有主从之分。
分布式存储系统可以理解为多台单机存储平台的各司其职、协同合作,统一的对外提供存储的服务。所以无论是储存非结构化数据的分布式文件系统,存储结构化数据的分布式,还是半结构化数据的分布式KV,在平台的设计上主要应该满足下述需求(但除了限于):基本读写功能、性能、可扩展性、可靠性、可用性。
1. 有中心管理节点 AND 存储节点有主从
此种架构的平台以GFS为代表,以下面系统为例表明,整体设计跟GFS类似,最近看到小米的分布式KV系统Pegasus用的是相同的架构设计方案。

从基本的读写功能来说,分布式文件系统主要提供文件的读/写/删功能,那么从那里读写?怎么读写?以哪个形式存储?也就是在后记所提及的数据定位跟存储引擎的问题
Master
在有中心控制节点的分布式文件系统,从哪里读写的任务基本是由中心控制节点完成的,即图中的Master节点。为了可完成这一项核心的任务,Master节点必须做两件比较重要的事情:
1. 存储节点信息和状况
对于分布式文件系统,从文件到某一台单机上的一块磁盘的某个位置,会有一个逻辑的拓扑结构以便分区扩展以及数据隔离等等。拓扑结构从上到下存储池、分区、服务器、磁盘、文件目录等。
Master节点必须保存整个集群的全局视图,为了提升性能,这个逻辑拓扑结构通常会缓存在存储中,定期地持久化在Master节点的磁盘上。
Master节点必须系统的所有数据节点和磁盘状态,如节点的上下线等,并对事件做出相应的处理来确保平台状态的正确性。

同时为了促使系统的数据分布跟资源使用最均衡,Master节点可以获得数据节点的容量、负荷等状况,供读写调度模块有策略的去分配可写的资源。
2. 文件读写的调度策略
由于没有采用类似Hash算法这种静态计算读写位置的方法,中心控制节点就必须担任起调度的角色。当客户端发起写请求时,第一步会至Master节点获取文件ID,Master节点按照客户端读写文件的大小、备份数等参数或者当前系统节点的状况跟权重,选择适合的节点和备份,返回给客户端一个文件ID,而这个文件ID包含了该文件多个副本位置信息。这样的弊端是不用将每个文件的映射关系都传输出来。而针对对象存储系统因为功能的应该,这个对象跟文件的映射关系是必应该保存的。
Master节点除了完成以上两种主要用途,还需担负保持副本数目和内容正确性的责任,因为即使它了解很多了,数据恢复调度的任务只是只能是它的,这里就先不展开了。
3.存储节点选主
对于存储节点有主从之分的系统,每个备份的主从节点的选定也必须Master节点来控制。
StorageNode
数据节点除了负责文件在单机平台上怎么进行内存,对于有主从之分的存储节点,各自还承担如何维持备份数据一致性的任务。归纳为下列几个要点:
1. 单机存储引擎的推动
主从存储节点在单机存储引擎的推动上几乎没有差异,解决的是文件如何存储的难题。对于不同的平台也有个区分是一个存储引擎负责一台机器所有硬盘的储存,还是一个磁盘一个存储引擎,我们此处以一个存储引擎负责一个磁盘的设计说明
分布式文件系统的内存引擎大多都是在单机文件系统之上,数据最后以文件的方式存在。而单机文件系统以目录的方式将文件组织出来。该平台基本延续了这一观念,是以目录为单位进行副本划分,而不是节点,和Swift一样称成为Partition,是备份的基本单位。以三备份为例,中心节点会按照策略选择三个不同的物理磁盘上构建同一个ID的Partition,在不同物理磁盘的同一个PartitionID下存储的文件是一样的。
这里也有另外一个问题,文件传输到单机文件系统上能否合并的难题。简单直接的做法,就是以一个个文件直接存储在选定的某个Partition目录下。这样的方法带来的弊端也是直接可见的,直接得到文件系统随机读写的功耗的考量,对于小文件读写比较多的画面来说,磁盘经常会变成整个系统的难题,然后不得不通过降低节点来进行吞吐能力的扩展。

所以该平台将多个文件追加合并写在一个相对较大且大小固定的文件里,将随机写转为了顺序写,实验证实可以大大提高单机存储的吞吐能力。这样的缓解方法带给的性能提高是显著,但是在推动上提高了一定的复杂性,合并必然时常带来定位文件的最后位置必须二次映射,即是在合并文件中的偏移。
2. 保证备份一致性
在确保备份一致性上,主从存储节点的角色就有一些差别了。对于Master节点选出的主存储节点,它必须按照主从一致性协议将数据推送至其他从节点,一般采取存储节点分主从的平台都会选取强一致协议,即主节点采用将数据发送给从节点收到响应成功后,才会将数据持久化至本地,返回用户顺利,这样用户读到的数据仍然是一致的。当然整个过程不是那么简单的,后续再一致性协议部分再展开。
3. 汇报消息,听从调度
对于存储节点必须维持跟Master节点的心跳信息,同时将自己当前的容量和资源使用状况汇报给Master节点。从控制系统的视角来说,这才产生了一个负反馈系统。
同时,存储节点处于待命状态,等待Master节点的派遣任务,比如说数据备份的修复迁移等。
Client
Client一般成为分布式文件系统的接入层,对写操作,接受流,将数据读取内存节点;对于读操作,从多副本中随机选取副本来调用。同时为了提升系统整体功耗和可用性,该平台的Client一般都会负责额外的功能
从性能角度来看,Master节点是不会成为平台瓶颈的,毕竟目前的服务器处理能力是很好的,无论是Master节点缓存的集群信息占用的存储,还是针对一个几万台机器的集群的调度,单机Master节点都是可以扛得住的。说道这里,在做平台性能检测时,对于分布式存储系统中的管控节点的性能,即管理流的画面要模拟覆盖到的。实验证明这种情景确实可看到了不少的性能问题。
那么针对有中心管理节点,数据节点有主从之分的平台,它的性能瓶颈是在哪里?根据理论预测,假设单机存储平台参数不当或代码实现引起的性能问题都未排除解决,即横向的性能改进基本依照预期。这样一个系统,对于小文件的读写场景,在有限的磁盘数量跟文件数目,如果数据分布的不是很分散,那么主要的性能瓶颈在于集群中这些磁盘的吞吐能力,而在大文件的读写场景,系统的难题在主节点的出口网卡流量。以三备份为例,主节点必须往两个从节点写数据,这时候主节点的出口网卡流量是入口网卡的两倍,如果出口入口均为千兆网卡那么入口网卡的流量一直没法走满到网卡最大流量的一半。所以在设计时就会以Partition为单位成为备份的基本单位,这样一来每个节点上面都有主从,每个节点的流量基本都可以走满。
性能分析先收住,分布式存储系统的功耗测试和改进是很重要的,涉及到的知识跟内容也非常多,有机会再展开。
从可用性的视角来看,如果不做高可用的设计,Master节点就是系统的单点。消除系统单点的方式太多,一般分布式平台中常直接使用Zookeeper来确保节点的高可用。所以虽然中心控制节点的单点弊端并没有那么严重的。相比而言,中心控制节点的调度策略变得更为重要,因为数据分布的能否均衡直接制约到平台对外服务的性能。

2. 无中心管理节点 AND 存储节点无主从
以Swift为例表明,从其基本架构可以看出,Swift 采用了完全对称、所有部件都可以扩充的分布式平台架构设计,系统无单点存在。去掉Proxy-Server层对象映射的逻辑,可被看成为要讨论的分布式文件系统,从另一个角度Proxy-Server也可以看做是分布式文件系统的客户端,只是在推动上跟对象存储的逻辑耦合相对非常紧密。
此外,对象存储逻辑层的认证服务、缓存服务忽略暂不探讨,Container-Server和Account-Server和Object-Server的设计基本一致,所以仅讨论Object-Server。
以下为Swift的基本构架图,包含主要各个模块

Client
Swift的对象业务逻辑跟底层的分布式文件系统耦合是非常近的,为了方便拆分理解,这里可以将Proxy-Server节点看做为分布式文件系统的Client端
抛开Proxy节点成为对象服务用途不谈,作为无中心控制节点系统Client端,它承担了相当重要的两个角色
1. 备份一致性的确保
Swift 采用 Quorum 协议,关于此协议内容就不赘述了。Quorum协议针对一致性的确保更灵活。Swift默认选择的是写到三个备份才算写成功,也能借助配置参数选择写完2个副本即返回,剩余副本有Object-Replicator保证副本数目的正确性。对于读操作,Swift默认选择任意读其中一个备份数据即返回,此种弱一致性模型是最可能读到旧版本数据的,不过它支持用户在读操作请求头中降低 x-newest=true 参数来同时加载 2 个副本的元数据信息,然后比较时间戳来确认哪些是最新版本,返回给用户最新数据。
对于Swift选择的最后一致性模型实现,光靠Client数据流来确保是不靠谱的,所以在StorageNode上会有进程定时检测备份是否一致,在Object-Replicator部分会说道。
2. 系统可靠性的确保

对于一个无中心的分布式文件系统来说分布式文件存储技术,系统可靠性的确保不是某一个节点可全权负责的。Proxy节点主要是在处理流的之后最大程度的去确保客户请求可处理成功。但当客户发送一个上传对象的请求时,Proxy节点看到一个存储节点故障了,应该怎样处理?
Swift引入了handoff节点,可理解为备用节点。其中,Swift的Ring对象的get_more_nodes方法,针对partition会返回一组handoff节点,如何挑选handoff节点先不展开,总体观念是尽量选择和故障节点不在一个逻辑域跟物理域,然后开始重试,重试次数由Proxy节点配置文件request_node_count 参数决定,默认是备份数的2倍。
StorageNode
Swift的StorageNode由下面几个组件构成。
Object Server,即单机的储存引擎推动,提供文件的元数据和内容传输。每个文件的的内容会以文件的方式传输在文件系统中,而元数据会成为文件属性来储存。每一个文件以生成的时间戳作为名字。
Object-Replicator,主要用于确保副本数目跟位置的正确性以及一致性。在Swift的实际使用中,有几个场景就会造成副本的次数和位置不恰当。先在这里简单例子,后面在说到数据恢复时会具体表明。如上文提到的临时写到handoff节点,Replicator会按照ring计算出的信息,把数据放到正确位置,再如因为添加了磁盘或机器造成ring发生差异,再入Proxy节点配置了写亲缘性分布式文件存储技术,Proxy节点会将数据优先写到某个分区,最后由Replicator把数据跨分区复制至正确的位置。在这些节点故障以及客户选择只写两备份就返回的画面下,副本会进入少备份的状况,这只是Replicator要做的事情。
Object-Replicator同时还能确保副本的一致性,以Partition/Suffix为基本单位(Suffix为Partition下的子目录),以每个文件时间戳计算的hash值保存在Partition目录下的hashes.pkl文件中,通过请求远端备份的Object-Server获取hashes.pkl和本地值对比,发现不一致时会采取推的方法升级远程副本,使用远程文件拷贝软件 rsync 来做数据的同步,rsync带 ignore-existing参数,对于文件名相同的文件会忽视拷贝,这样就导致了全量拷贝。这样在远端备份同一个文件名的目录下可能会存储在不同版本的数据文件,这个Object-Server在处理读操作的之后会选取时间最新的数据返回。从这个视角来看,Object-Replicator对确保副本的一致性起至了作用。
Object-Auditor:主要用于测量副本数据能否正确,当看到比特级的错误,文件将被隔离,这样远程Object-Replicator检测至副本缺少时会将正确的副本推送过来。
Object-Updater:主要是解决对象存储的元数据的升级问题,简要表明下,文件成功建立后会将对象名升级至Container-Server,当Object-Server由于高负载的缘由而未能及时升级时,任务即将被保存到本地文件,以便服务恢复后进行异步更新;Updater服务主要就是负责平台恢复正常后扫描任务做相应的升级处理。
此篇只对架构进行了详细的表明,而针对Swift的核心关键Ring的谋求暂时还没展开。Ring作为数据定位的关键推动,再具体表明。
没有中心控制节点,所以Swift的可靠性的确保落在各个节点上,责任分工在上文也有所表述,这同时也必须每个节点都应拥有整个集群的配置信息,也就是Ring文件能够加强工作。所以,一旦Ring发生改变之后必须同步至集群的所有节点,否则系统就无法正常工作了。虽然针对Swift系统来说只有管理员在做节点增减等运维操作之后才能改变Ring结构,然后同步至各个节点,但是仍然在制造使用中,还是最好是必须一个第三方监控进程,对比各个节点Ring文件的MD5,保证集群中所有节点的Ring文件仍然保持一致.
从性能的视角来说,对于无中心管理节点,且数据节点业务主从之分的平台,同样也必须考量集中典型的场景,来分别考量其性能瓶颈。同样也必须假定单机存储平台参数不当或代码实现引起的性能问题都未排除解决,即横向的性能改进基本满足需求。
对于小文件的读写场景,在有限的磁盘数量和文件数目,性能瓶颈也会受限集群中这些磁盘的吞吐能力,再加上即使没有对小文件做合并处理,性能会很受制约。Swift成为对象存储系统,存在的性能瓶颈和困惑不仅仅于此,有机会再展开描述。
而在大文件的写场景,系统的难题在Proxy节点的出口网卡流量。以三备份为例,Proxy节点默认应该写到三个备份才返回成功,Proxy节点出口网卡流量是入口网卡的三倍,在相同的机器硬件条件下,性能大大受限,只能借助扩展网卡或机器的方法能够超过同样的性能。
以上可以看出,分布式文件系统的构架相当难适合于所有的画面,如何进行选取和设计,常常优先围绕需求来选取和推动,留有扩充余地再不断地优化系统。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-139990-1.html
^ω^
活在光环中的女人
2的不会卡
若可以住人