Openstack Swift 原理、架构与 API 介绍

Openstack Swift 开源云存储技术解析

OpenStack Swift 开源项目提供了弹性可伸缩、高可用的分布式对象存储服务,适合存储大规模非结构化数据。本文将深入介绍 Swift 的基本设计原理、对称式的系统架构和 RESTful API。

OpenStack Swift 原理、架构与 API 介绍

背景与概览

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

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

基本原理

一致性散列(Consistent Hashing)

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

一致性散列

如图 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 协议示例

环的数据结构

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

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

图 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 组件包括:

API

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

GET /v1/ 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 总结
资源类型URLGETPUTPOSTDELETEHEAD
账户/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 在市场上的垄断地位,推动云计算在朝着更加开放和可互操作的方向前进。


参考资料

学习