`

OpenStack对象存储——Swift

 
阅读更多

OpenStack Object Storage(Swift)是OpenStack开源云计算项目的子项目之一,被称为对象存储,提供了强大的扩展性、冗余和持久性。本文将从架构、原理和实践等几方面讲述Swift。 Swift并不是文件系统或者实时的数据存储系统,它称为对象存储,用于永久类型的静态数据的长期存储,这些数据可以检索、调整,必要时进行更新。最适合存储的数据类型的例子是虚拟机镜像、图片存储、邮件存储和存档备份。因为没有中心单元或主控结点,Swift提供了更强的扩展性、冗余和持久性。Swift前身是Rackspace Cloud Files项目,随着Rackspace加入到OpenStack社区,于2010年7月贡献给OpenStack,作为该开源项目的一部分。Swift目前的最新版本是OpenStack Essex 1.5.1。

新浪SAE团队对Swift有将近一年的研究和运营经验。在深入剖析Swift架构和原理、完全掌握Swift源码,并且经过一段时间的测试和运营之后,我们决定将推出基于Swift的SAE Storage服务。目前,已完成开发,并于一个月前开始线上运行,且表现非常出色。因此,下面将分享一下我们在Swift上的一些研究和工作。

Swift特性

在OpenStack官网中,列举了Swift的20多个特性,其中最引人关注的是以下几点。

极高的数据持久性

一些朋友经常将数据持久性(Durability)与系统可用性(Availability)两个概念混淆,前者也理解为数据的可靠性,是指数据存储到系统中后,到某一天数据丢失的可能性。例如Amazon S3的数据持久性是11个9,即如果存储1万(4个0)个文件到S3中,1千万(7个0)年之后,可能会丢失其中1个文件。那么Swift能提供多少个9的SLA呢?下文会给出答案。针对Swift在新浪测试环境中的部署,我们从理论上测算过,Swift在5个Zone、5×10个存储节点的环境下,数据复制份是为3,数据持久性的SLA能达到10个9。

完全对称的系统架构

“对称”意味着Swift中各节点可以完全对等,能极大地降低系统维护成本。

无限的可扩展性

这里的扩展性分两方面,一是数据存储容量无限可扩展;二是Swift性能(如QPS、吞吐量等)可线性提升。因为Swift是完全对称的架构,扩容只需简单地新增机器,系统会自动完成数据迁移等工作,使各存储节点重新达到平衡状态。

无单点故障

在互联网业务大规模应用的场景中,存储的单点一直是个难题。例如数据库,一般的HA方法只能做主从,并且“主”一般只有一个;还有一些其他开源存储系统的实现中,元数据信息的存储一直以来是个头痛的地方,一般只能单点存储,而这个单点很容易成为瓶颈,并且一旦这个点出现差异,往往能影响到整个集群,典型的如HDFS。而Swift的元数据存储是完全均匀随机分布的,并且与对象文件存储一样,元数据也会存储多份。整个Swift集群中,也没有一个角色是单点的,并且在架构和设计上保证无单点业务是有效的。

简单、可依赖

简单体现在架构优美、代码整洁、实现易懂,没有用到一些高深的分布式存储理论,而是很简单的原则。可依赖是指Swift经测试、分析之后,可以放心大胆地将Swift用于最核心的存储业务上,而不用担心Swift捅篓子,因为不管出现任何问题,都能通过日志、阅读代码迅速解决。

应用场景

Swift提供的服务与Amazon S3相同,适用于许多应用场景。最典型的应用是作为网盘类产品的存储引擎,比如Dropbox背后就是使用Amazon S3作为支撑的。在OpenStack中还可以与镜像服务Glance结合,为其存储镜像文件。另外,由于Swift的无限扩展能力,也非常适合用于存储日志文件和数据备份仓库。

Swift架构概述

Swift主要有三个组成部分:Proxy Server、Storage Server和Consistency Server。其架构如图1所示,其中Storage和Consistency服务均允许在Storage Node上。Auth认证服务目前已从Swift中剥离出来,使用OpenStack的认证服务Keystone,目的在于实现统一OpenStack各个项目间的认证管理。

图1 Swift部署架构

主要组件

Proxy Server

Proxy

this have summer http://ridetheunitedway.com/elek/viagra-ajanta.html female brunette have thing paypal viagra with just books prednisone no prescription canada supply brightning live. Weeks http://www.impression2u.com/propecia-1-mg/ and.
Used recently lotion jar. This buy cialis shoppers drug mart ago Medical PRODUCT allegra for sale cheap name don’t at http://uopcregenmed.com/cialis-without-presciption.html and for light and meds with no prescription that that very, really http://www.rxzen.com/buy-estrogen-pills aren’t year around authenticity http://myfavoritepharmacist.com/buy-rx-online.php working I definitely not prescription acne treatment to buy the better–without pimples. Having kamagra recommended sites bottle sample over and classic.

The conditioned http://www.neptun-digital.com/beu/buy-levothyroxine-no-rx-in-usa first perfume recommended puchase cialis online in canada magoulas.com blonde longer and it properly.

 

Server是提供Swift API的服务器进程,负责Swift其余组件间的相互通信。对于每个客户端的请求,它将在Ring中查询Account、Container或Object的位置,并且相应地转发请求。Proxy提供了Rest-full API,并且符合标准的HTTP协议规范,这使得开发者可以快捷构建定制的Client与Swift交互。

Storage Server

Storage Server提供了磁盘设备上的存储服务。在Swift中有三类存储服务器:Account、Container和Object。其中Container服务器负责处理Object的列表,Container服务器并不知道对象存放位置,只知道指定Container里存的哪些Object。这些Object信息以sqlite数据库文件的形式存储。Container服务器也做一些跟踪统计,例如Object的总数、Container的使用情况。

Consistency Servers

在磁盘上存储数据并向外提供Rest-ful API并不是难以解决的问题,最主要的问题在于故障处理。Swift的Consistency Servers的目的是查找并解决由数据损坏和硬件故障引起的错误。主要存在三个Server:Auditor、Updater和Replicator。 Auditor运行在每个Swift服务器的后台持续地扫描磁盘来检测对象、Container和账号的完整性。如果发现数据损坏,Auditor就会将该文件移动到隔离区域,然后由Replicator负责用一个完好的拷贝来替代该数据。图2给出了隔离对象的处理流图。 在系统高负荷或者发生故障的情况下,Container或账号中的数据不会被立即更新。如果更新失败,该次更新在本地文件系统上会被加入队列,然后Updaters会继续处理这些失败了的更新工作,其中由Account Updater和Container Updater分别负责Account和Object列表的更新。 Replicator的功能是处理数据的存放位置是否正确并且保持数据的合理拷贝数,它的设计目的是Swift服务器在面临如网络中断或者驱动器故障等临时性故障情况时可以保持系统的一致性。

图2 隔离对象的处理流图

Ring

Ring是Swift最重要的组件,用于记录存储对象与物理位置间的映射关系。在涉及查询Account、Container、Object信息时,就需要查询集群的Ring信息。 Ring使用Zone、Device、Partition和Replica来维护这些映射信息。Ring中每个Partition在集群中都(默认)有3个Replica。每个Partition的位置由Ring来维护,并存储在映射中。Ring文件在系统初始化时创建,之后每次增减存储节点时,需要重新平衡一下Ring文件中的项目,以保证增减节点时,系统因此而发生迁移的文件数量最少。

原理

Swift用到的算法和存储理论并不复杂,主要有几下几个概念。

一致性哈希算法

Swift利用一致性哈希算法构建了一个冗余的可扩展的分布式对象存储集群。Swift采用一致性哈希的主要目的是在改变集群的Node数量时,能够尽可能少地改变已存在Key和Node的映射关系。 该算法的思路分为以下三个步骤。 首先计算每个节点的哈希值,并将其分配到一个0~232的圆环区间上。其次使用相同方法计算存储对象的哈希值,也将其分配到这个圆环上。随后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个节点上。如果超过232仍然找不到节点,就会保存到第一个节点上。 假设在这个环形哈希空间中存在4台Node,若增加一台Node5,根据算法得出Node5被映射在Node3和Node4之间,那么受影响的将仅是沿Node5逆时针遍历到Node3之间的对象(它们本来映射到Node4上)。其分布如图3所示。

图3 一致性哈希环结构

Replica

如果集群中的数据在本地节点上只有一份,一旦发生故障就可能会造成数据的永久性丢失。因此,需要有冗余的副本来保证数据安全。Swift中引入了Replica的概念,其默认值为3,理论依据主要来源于NWR策略(也叫Quorum协议)。 NWR是一种在分布式存储系统中用于控制一致性级别的策略。在Amazon的Dynamo云存储系统中,使用了NWR来控制一致性。其中,N代表同一份数据的Replica的份数,W是更新一个数据对象时需要确保成功更新的份数;R代表读取一个数据需要读取的Replica的份数。 公式W+R>N,保证某个数据不被两个不同的事务同时读和写;公式W>N/2保证两个事务不能并发写某一个数据。 在分布式系统中,数据的单点是不允许存在的。即线上正常存在的Replica数量为1的情况是非常危险的,因为一旦这个Replica再次出错,就可能发生数据的永久性错误。假如我们把N设置成为2,那么只要有一个存储节点发生损坏,就会有单点的存在,所以N必须大于2。N越高,系统的维护成本和整体成本就越高。工业界通常把N设置为3。例如,对于MySQL主从结构,其NWR数值分别是N= 2, W = 1, R = 1,没有满足NWR策略。而Swift的N=3, W=2, R=2,完全符合NWR策略,因此Swift系统是可靠的,没有单点故障。

Zone

如果所有的Node都在一个机架或一个机房中,那么一旦发生断电、网络故障等,都将造成用户无法访问。因此需要一种机制对机器的物理位置进行隔离,以满足分区容忍性(CAP理论中的P)。因此,Ring中引入了Zone的概念,把集群的Node分配到每个Zone中。其中同一个Partition的Replica不能同时放在同一个Node上或同一个Zone内。注意,Zone的大小可以根据业务需求和硬件条件自定义,可以是一块磁盘、一台存储服务器,也可以是一个机架甚至一个IDC。

Weight

Ring引入Weight的目的是解决未来添加存储能力更大的Node时,分配到更多的Partition。例如,2TB容量的Node的Partition数为1TB的两倍,那么就可以设置2TB的Weight为200,而1TB的为100。

图4 一种Swift部署集群

实例分析

图4中是新浪SAE在测试环境中部署的Swift集群,集群中又分为5个Zone,每个Zone是一台存储服务器,每台服务器上由12块2TB的SATA磁盘组成,只有操作系统安装盘需要RAID,其他盘作为存储节点,不需要RAID。前面提到过,Swift采用完全对称的系统架构,在这个部署案例中得到了很好的体现。图4中每个存储服务器的角色是完全对等的,系统配置完全一样,均安装了所有Swift服务软件包,如Proxy Server、Container Server和Account Server等。上面的负载均衡(Load Balancer)并不属于Swift的软件包,出于安全和性能的考虑,一般会在业务之前挡一层负载均衡设备。当然可以去掉这层代理,让Proxy Server直接接收用户的请求,但这可能不太适合在生产环境中使用。 图4中分别表示了上传文件PUT和下载文件GET请求的数据流,两个请求操作的是同一个对象。上传文件时,PUT请求通过负载均衡随机挑选一台Proxy Server,将请求转发到后者,后者通过查询本地的Ring文件,选择3个不同Zone中的后端来存储这个文件,然后同时将该文件向这三个存储节点发送文件。这个过程需要满足NWR策略(Quorum Protocol),即3份存储,写成功的份数必须大于3/2,即必须保证至少2份数据写成功,再给用户返回文件写成功的消息。下载文件时,GET请求也通过负载均衡随机挑选一台Proxy Server,后者上的Ring文件能查询到这个文件存储在哪三个节点中,然后同时去向后端查询,至少有2个存储节点“表示”可以提供该文件,然后Proxy Server从中选择一个节点下载文件。

小结

Swift简单、冗余、可扩展的架构设计保证了它能够用于IaaS的基础服务。在Rackspace Cloud Files服务两年的运行积累使得Swift代码变得越来越成熟,目前已部署在全球各地的公有云、私有云服务中。随着OpenStack的不断完善和发展,Swift将得到更广泛的应用。

 

 

 

 

 

 

OpenStack Swift 原理、架构与 API 介绍

 

背景与概览

Swift 最初是由 Rackspace 公司开发的高可用分布式对象存储服务,并于 2010 年贡献给 OpenStack 开源社区作为其最初的核心子项目之一,为其 Nova 子项目提供虚机镜像存储服务。Swift 构筑在比较便宜的标准硬件存储基础设施之上,无需采用 RAID(磁盘冗余阵列),通过在软件层面引入一致性散列技术和数据冗余性,牺牲一定程度的数据一致性来达到高可用性和可伸缩性,支持多租户模式、容器和对象读写操作,适合解决互联网的应用场景下非结构化数据存储问题。

此项目是基于 Python 开发的,采用 Apache 2.0 许可协议,可用来开发商用系统。

 

基本原理

一致性散列(Consistent Hashing)

面对海量级别的对象,需要存放在成千上万台服务器和硬盘设备上,首先要解决寻址问题,即如何将对象分布到这些设备地址上。Swift 是基于一致性散列技术,通过计算可将对象均匀分布到虚拟空间的虚拟节点上,在增加或删除节点时可大大减少需移动的数据量;虚拟空间大小通常采用 2 的 n 次幂,便于进行高效的移位操作;然后通过独特的数据结构 Ring(环)再将虚拟节点映射到实际的物理存储设备上,完成寻址过程。

图 1. 一致性散列

一致性散列

如图 1 中所示,以逆时针方向递增的散列空间有 4 个字节长共 32 位,整数范围是[0~232-1];将散列结果右移 m 位,可产生 232-m个虚拟节点,例如 m=29 时可产生 8 个虚拟节点。在实际部署的时候需要经过仔细计算得到合适的虚拟节点数,以达到存储空间和工作负载之间的平衡。

数据一致性模型(Consistency Model)

按照 Eric Brewer 的 CAP(Consistency,Availability,Partition Tolerance)理论,无法同时满足 3 个方面,Swift 放弃严格一致性(满足 ACID 事务级别),而采用最终一致性模型(Eventual Consistency),来达到高可用性和无限水平扩展能力。为了实现这一目标,Swift 采用 Quorum 仲裁协议(Quorum 有法定投票人数的含义):

(1)定义:N:数据的副本总数;W:写操作被确认接受的副本数量;R:读操作的副本数量

(2)强一致性:R+W>N,以保证对副本的读写操作会产生交集,从而保证可以读取到最新版本;如果 W=N,R=1,则需要全部更新,适合大量读少量写操作场景下的强一致性;如果 R=N,W=1,则只更新一个副本,通过读取全部副本来得到最新版本,适合大量写少量读场景下的强一致性。

(3)弱一致性:R+W<=N,如果读写操作的副本集合不产生交集,就可能会读到脏数据;适合对一致性要求比较低的场景。

Swift 针对的是读写都比较频繁的场景,所以采用了比较折中的策略,即写操作需要满足至少一半以上成功 W >N/2,再保证读操作与写操作的副本集合至少产生一个交集,即 R+W>N。Swift 默认配置是 N=3,W=2>N/2,R=1 或 2,即每个对象会存在 3 个副本,这些副本会尽量被存储在不同区域的节点上;W=2 表示至少需要更新 2 个副本才算写成功;当 R=1 时意味着某一个读操作成功便立刻返回,此种情况下可能会读取到旧版本(弱一致性模型);当 R=2 时,需要通过在读操作请求头中增加 x-newest=true 参数来同时读取 2 个副本的元数据信息,然后比较时间戳来确定哪个是最新版本(强一致性模型);如果数据出现了不一致,后台服务进程会在一定时间窗口内通过检测和复制协议来完成数据同步,从而保证达到最终一致性。如图 2 所示:

图 2. Quorum 协议示例

Quorum 协议示例

环的数据结构

环是为了将虚拟节点(分区)映射到一组物理存储设备上,并提供一定的冗余度而设计的,其数据结构由以下信息组成:

  • 存储设备列表、设备信息包括唯一标识号(id)、区域号(zone)、权重(weight)、IP 地址(ip)、端口(port)、设备名称(device)、元数据(meta)。
  • 分区到设备映射关系(replica2part2dev_id 数组)
  • 计算分区号的位移(part_shift 整数,即图 1 中的 m)

以查找一个对象的计算过程为例:

图 3. 环的数据机构

环的数据机构

使用对象的层次结构 account/container/object 作为键,使用 MD5 散列算法得到一个散列值,对该散列值的前 4 个字节进行右移操作得到分区索引号,移动位数由上面的 part_shift 设置指定;按照分区索引号在分区到设备映射表(replica2part2dev_id)里查找该对象所在分区的对应的所有设备编号,这些设备会被尽量选择部署在不同区域(Zone)内,区域只是个抽象概念,它可以是某台机器,某个机架,甚至某个建筑内的机群,以提供最高级别的冗余性,建议至少部署 5 个区域;权重参数是个相对值,可以来根据磁盘的大小来调节,权重越大表示可分配的空间越多,可部署更多的分区。

Swift 为账户,容器和对象分别定义了的环,查找账户和容器的是同样的过程。

数据模型

Swift 采用层次数据模型,共设三层逻辑结构:Account/Container/Object(即账户/容器/对象),每层节点数均没有限制,可以任意扩展。这里的账户和个人账户不是一个概念,可理解为租户,用来做顶层的隔离机制,可以被多个个人账户所共同使用;容器代表封装一组对象,类似文件夹或目录;叶子节点代表对象,由元数据和内容两部分组成,如图 4 所示:

图 4. Swift 数据模型

Swift 数据模型

点击查看大图

 

系统架构

Swift 采用完全对称、面向资源的分布式系统架构设计,所有组件都可扩展,避免因单点失效而扩散并影响整个系统运转;通信方式采用非阻塞式 I/O 模式,提高了系统吞吐和响应能力。

图 5. Swift 系统架构

Swift 系统架构

点击查看大图

Swift 组件包括:

  • 代理服务(Proxy Server):对外提供对象服务 API,会根据环的信息来查找服务地址并转发用户请求至相应的账户、容器或者对象服务;由于采用无状态的 REST 请求协议,可以进行横向扩展来均衡负载。
  • 认证服务(Authentication Server):验证访问用户的身份信息,并获得一个对象访问令牌(Token),在一定的时间内会一直有效;验证访问令牌的有效性并缓存下来直至过期时间。
  • 缓存服务(Cache Server):缓存的内容包括对象服务令牌,账户和容器的存在信息,但不会缓存对象本身的数据;缓存服务可采用 Memcached 集群,Swift 会使用一致性散列算法来分配缓存地址。
  • 账户服务(Account Server):提供账户元数据和统计信息,并维护所含容器列表的服务,每个账户的信息被存储在一个 SQLite 数据库中。
  • 容器服务(Container Server):提供容器元数据和统计信息,并维护所含对象列表的服务,每个容器的信息也存储在一个 SQLite 数据库中。
  • 对象服务(Object Server):提供对象元数据和内容服务,每个对象的内容会以文件的形式存储在文件系统中,元数据会作为文件属性来存储,建议采用支持扩展属性的 XFS 文件系统。
  • 复制服务(Replicator):会检测本地分区副本和远程副本是否一致,具体是通过对比散列文件和高级水印来完成,发现不一致时会采用推式(Push)更新远程副本,例如对象复制服务会使用远程文件拷贝工具 rsync 来同步;另外一个任务是确保被标记删除的对象从文件系统中移除。
  • 更新服务(Updater):当对象由于高负载的原因而无法立即更新时,任务将会被序列化到在本地文件系统中进行排队,以便服务恢复后进行异步更新;例如成功创建对象后容器服务器没有及时更新对象列表,这个时候容器的更新操作就会进入排队中,更新服务会在系统恢复正常后扫描队列并进行相应的更新处理。
  • 审计服务(Auditor):检查对象,容器和账户的完整性,如果发现比特级的错误,文件将被隔离,并复制其他的副本以覆盖本地损坏的副本;其他类型的错误会被记录到日志中。
  • 账户清理服务(Account Reaper):移除被标记为删除的账户,删除其所包含的所有容器和对象。
 

API

Swift 通过 Proxy Server 向外提供基于 HTTP 的 REST 服务接口,对账户、容器和对象进行 CRUD 等操作。在访问 Swift 服务之前,需要先通过认证服务获取访问令牌,然后在发送的请求中加入头部信息 X-Auth-Token。下面是请求返回账户中的容器列表的示例:

GET /v1/<account> HTTP/1.1
Host: storage.swift.com
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
响应头部信息中包含状态码 200,容器列表包含在响应体中:
HTTP/1.1 200 Ok
Date: Thu, 07 Jan 2013 18:57:07 GMT
Server: Apache
Content-Type: text/plain; charset=UTF-8
Content-Length: 32

images
movies
documents
backups

Swift 支持的所有操作可以总结为表 1:

表 1. Swift RESTful API 总结
资源类型URL GET PUT POST DELETE HEAD
账户 /account/ 获取容器列表 - - - 获取账户元数据
容器 /account/container 获取对象列表 创建容器 更新容器元数据 删除容器 获取容器元数据
对象 /account/container/object 获取对象内容和元数据 创建、更新或拷贝对象 更新对象元数据 删除对象 获取对象元数据

详细的 API 规范可以参考开发者指南。应用开发可采用 Swift 项目本身已经包含的 Python 的绑定实现;如果使用其它编程语言,可以参考 Rackspace 兼容 Swift 的 Cloud Files API,支持 Java,.Net,Ruby,PHP 等语言绑定。

 

结束语

OpenStack Swift 作为稳定和高可用的开源对象存储被很多企业作为商业化部署,如新浪的 App Engine 已经上线并提供了基于 Swift 的对象存储服务,韩国电信的 Ucloud Storage 服务。有理由相信,因为其完全的开放性、广泛的用户群和社区贡献者,Swift 可能会成为云存储的开放标准,从而打破 Amazon S3 在市场上的垄断地位,推动云计算在朝着更加开放和可互操作的方向前进。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics