haizdl
作者haizdl·2022-04-29 11:57
技术经理·大连

分布式存储技术探讨系列:Swift

字数 3784阅读 977评论 0赞 0

分布式存储技术探讨系列:Swift

## 1. 什么是Swift ?

首先,我们从 OpenStack的官方网站上,可以看到Swift的定义: “The OpenStack Object Store project , known as Swift, offers cloud storage software so that you can store and retrieve lots of data with a simple API. It's built for scale and optimized for durability, availability, and concurrency across the entire data set . Swift is ideal for storing unstructured data that can grow without bound .” 。 从它的定义上我们可以明确它是OpenStack框架当中的一个对象存储组件,它专门用于海量非结构化数据的存储,而且它具备以下特性:

(1) 扩展性( It's built for scale ):意味着节点的横向扩展能力,这是它的核心;
(2) 并发能力(Concurrency):意味着高并发处理机制,必须是以分布式集群架构为依托的;
(3) 高可用性(Availability): 意味着节点的故障或者架构的变化对它的影响很小。

接下来,我们从其架构原理以及读写原理上来分析其如何支撑定义当中所提到的各个特性。

2. Swift 架构原理

2.1 Swift 存储功能架构

从功能角度来讲,Swift存储系统仅仅提供对象存储服务。从客户端发起请求到Swift存储提供数据服务整个过程需要经过代理层和数据存储层两部分。

代理层向用户提供Swift的API接口,对于客户端的Put&Get请求,代理层首先会查找被操作实体对象的物理位置,然后会将请求发送给存储节点层获取对象存取的服务;由于客户端的对象存取请求是通过无状态的REST协议完成的,因此我们可以在外层加负载均衡。

具体如图2.1所示:

图2.1 Swift存储系统功能图


Swift-PRoxy**

(1)提供 REST API 给客户端;
(2)无状态服务模式,由多个代理节点组成一个集群;
(3)将客户端请求转给某个存储节点上的数据读写服务,完成客户端请求;

这里,可能会有2个问题:“ Proxy如何知道某个对象应该存储到存储节点层的具体位置?Proxy如何知道要查找的对象到底已经存储到什么位置了?

暂且我们带着问题往下读。

Swift-Storage-Nodes**

(1)数据存取寻址服务(Account、Container、Object);
(2)数据一致性保护服务(Replicator、Updater、Auditor);

这里,同样会有问题:“ 这些服务到底有何作用,扮演何种角色?

暂且我们带着问题往下读。

2.2 Swift 数据对象组件**

我们先看Swift的数据模型,通俗讲就是Swift当中的对象数据是以什么样的形式在存储系统里面组织起来的,基本上我们认为Swift 的数据模型使用了以下三个概念:

账户(Account)**
OpenStack天生就是为云而生的框架,Swift作为它的核心组件之一,那么自然有租户的概念,暂且我们把这个Account理解为类似租户的用户命名空间隔离的概念。Account的配置数据和其下级Container的列表数据都会被保存在SQLite数据库当中。

容器(Container)**
容器类似于文件系统中的目录,主要目的就是将对象数据进行逻辑分割,由用户自定义,同样它包含自身的配置数据和容器内的对象列表数据,也是被保存在SQLite 数据库中。

对象(Object)**
对象即客户端对象请求对应的物理对象文件,包括数据本身和数据对应的元数据,它们会以文件形式保存在存储节点上的文件系统上。

图2.2 Swift 数据对象组件图

从图2.2当中,我们可以看到Acount/Container/Object的组成关系,同时也能看到真正支撑这些对象服务的存储服务器节点与他们的关系。每个对象在不同的服务器上都会有相应的服务进程(Acount Service、Container Service、Object Service)为其对象提供服务,所有节点上的同类服务组成了共同的对象服务。

2.3 Swift 数据映射过程**

在2.2节当中,我们详细介绍了Swift数据的组织形式,但是并没有阐述如何放置和寻找数据。要解决这个问题,就需要Ring这个概念了。Swift 根据由管理员配置的 Ring 使用相对简单直接的算法来确定对象的存放位置。接下来结合图2.3来看什么是Ring。

图2.3 Swift 数据映射图

如图2.3所示,展示了Swift整个寻址的过程。

首先,Region、Zone、Node的概念实际上可以理解为用户为了管理而设定的层级逻辑概念,同时也是为了完成故障隔离策略设定的。每一个对象通过对其名称的哈希计算可以得到相应的地址信息。

HASH(Acount/Container/Object)= XXXXXXXXXXXXXXXX

这个地址信息,可以通过不同位段信息来区分它的Region、Zone、Node等信息,从而达到将其三个副本隔离于不同的物理故障隔离域的目标,通过这步映射实现了分布式副本的故障隔离。但是如何寻址,也就是说根据对象的地址信息如何从众多物理服务器上寻找它的数据副本的具体位置?仅仅从地址索引方面是无法找到对象数据的具体位置的,最终还要依赖于Ring。

Acount、Container数据对象都会有自己的Ring,这些Ring组成了一系列数据结构。存放于Proxy节点和Storage节点,Proxy上的Ring用来帮助客户端进行对象数据的寻址,Storage节点上的Ring用来帮助后台检查和恢复数据,保障数据的一致性。

2.4 Swift Ring

在2. 3 节当中,我们 介绍了数据映射寻址的过程 。 其中有一个重要的角色就是Ring。那么Ring是什么样的数据结构,为什么Swift会选择这种数据结构呢? 面对海量级别的对象,需要存放在成千上万台服务器和硬盘设备上,首先要解决寻址问题。Swift采用一致性hash算法来实现PUT,GET账户,容器和对象文件的高效寻址。一致性散列技术,通过计算可将对象均匀分布到虚拟空间的虚拟节点上,在增加或删除节点时可大大减少需移动的数据量;虚拟空间大小通常采用 2 的 N 次幂,便于进行高效的移位操作;

图2. 4 Swift Ring

如图2.4,每一Ring环上面有N个虚拟节点vX,虚拟节点映射对应M个物理节点pX,经过对数据对象的地址哈希计算之后可以定位它在Ring当中的具体位置,当Ring当中增加节点或者是减少节点时,哈希一致性算法可以保障整个Ring上的数据分布需要移动的数据只有黄色部分对应的三个点,而不是所有有点上的数据,这个特性保障了集群数据移动的小规模性,在这种哈希一致性算法当中,在数据结构当中加入虚拟节点之后,那么整个Ring环上的数据就更具备稳定性了,因为虚拟节点是相对固定的,这种相对固定性使得大部分数据经过哈希计算之后还能保持原有的位置稳定性。

2.5 Swift数据读写原理**

按照CAP理论, 任何数据存储系统 无法同时满足 三 个方面 :Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),于是 Swift 放弃严格一致性,而采用最终一致性模型(Eventual Consistency), 保障其他两个方面的极致 。为了实现这一目标,Swift 采用 Quorum 仲裁协议:

N:数据的副本总数;
W : 写操作被确认接受的副本数量;
R:读操作的 需要读取的 副本数量 。

我们举个例子来说明强弱一致性,假设N=3,如果写完3个副本算是完整的IO过程,即W=3,那么读只需要读其中任何一个副本,R=1,这就算是强一致。Ceph就是采用的这种算法。如果写完2个副本算是完整的IO过程,即W=2,那么读要求读到两个副本并且校验之后才算读取成功,R=2,这也算强一致性。但是如果读取到一个副本就返回的化,R=1,必然存在读脏的可能,这算弱一致性,Swift采用的就是这种算法。总结来看,当R+W>N的时候,这算强一致;当R+W<=N的时候,这算弱一致性。

3. 结语**

总结来看,Swift是OpenStack云计算框架下的对象存储组件。它是基于对象地址索引区分实现副本的故障隔离分布,是基于逻辑分层Ring结构并在Ring内利用哈希一致性算法实现对物理存储设备的寻址管理和数据移动管理。它利用若一致性的数据读写算法来支撑它的大规模高并发性。从架构原理上来看,它的适用场合相对比较窄,从应用接口上来看比较单一,从底层数据映射数据结构来看,它不太适合大规模的碎小数据存储,会导致它的Ring数据结构规模级数增大。但是它适合海量的非结构化大数据的存储场景。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

本文隶属于专栏

最佳实践
不同的领域,都有先行者,实践者,用他们的最佳实践来加速更多企业的建设项目落地。

作者其他文章

相关文章

相关资料

X社区推广