OpenStack Swift 开源项目提供了弹性可伸缩、高可用的分布式对象存储服务,适合存储大规模非结构化数据。本文将深刻介绍 Swift 的基本设计原理、对称式的系统架构和 RESTful API。算法
Swift 最初是由 Rackspace 公司开发的高可用分布式对象存储服务,并于 2010 年贡献给 OpenStack 开源社区做为其最初的核心子项目之一,为其 Nova 子项目提供虚机镜像存储服务。Swift 构筑在比较便宜的标准硬件存储基础设施之上,无需采用 RAID(磁盘冗余阵列),经过在软件层面引入一致性散列技术和数据冗余性,牺牲必定程度的数据一致性来达到高可用性和可伸缩性,支持多租户模式、容器和对象读写操做,适合解决互联网的应用场景下非结构化数据存储问题。数据库
此项目是基于 Python 开发的,采用 Apache 2.0 许可协议,可用来开发商用系统。编程
面对海量级别的对象,须要存放在成千上万台服务器和硬盘设备上,首先要解决寻址问题,即如何将对象分布到这些设备地址上。Swift 是基于一致性散列技术,经过计算可将对象均匀分布到虚拟空间的虚拟节点上,在增长或删除节点时可大大减小需移动的数据量;虚拟空间大小一般采用 2 的 n 次幂,便于进行高效的移位操做;而后经过独特的数据结构 Ring(环)再将虚拟节点映射到实际的物理存储设备上,完成寻址过程。swift
如图 1 中所示,以逆时针方向递增的散列空间有 4 个字节长共 32 位,整数范围是[0~232-1];将散列结果右移 m 位,可产生 232-m个虚拟节点,例如 m=29 时可产生 8 个虚拟节点。在实际部署的时候须要通过仔细计算获得合适的虚拟节点数,以达到存储空间和工做负载之间的平衡。数组
按照 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 所示:异步
环是为了将虚拟节点(分区)映射到一组物理存储设备上,并提供必定的冗余度而设计的,其数据结构由如下信息组成:
以查找一个对象的计算过程为例:
使用对象的层次结构 account/container/object 做为键,使用 MD5 散列算法获得一个散列值,对该散列值的前 4 个字节进行右移操做获得分区索引号,移动位数由上面的 part_shift 设置指定;按照分区索引号在分区到设备映射表(replica2part2dev_id)里查找该对象所在分区的对应的全部设备编号,这些设备会被尽可能选择部署在不一样区域(Zone)内,区域只是个抽象概念,它能够是某台机器,某个机架,甚至某个建筑内的机群,以提供最高级别的冗余性,建议至少部署 5 个区域;权重参数是个相对值,能够来根据磁盘的大小来调节,权重越大表示可分配的空间越多,可部署更多的分区。
Swift 为帐户,容器和对象分别定义了的环,查找帐户和容器的是一样的过程。
Swift 采用层次数据模型,共设三层逻辑结构:Account/Container/Object(即帐户/容器/对象),每层节点数均没有限制,能够任意扩展。这里的帐户和我的帐户不是一个概念,可理解为租户,用来作顶层的隔离机制,能够被多个我的帐户所共同使用;容器表明封装一组对象,相似文件夹或目录;叶子节点表明对象,由元数据和内容两部分组成,如图 4 所示:
系统架构
Swift 采用彻底对称、面向资源的分布式系统架构设计,全部组件均可扩展,避免因单点失效而扩散并影响整个系统运转;通讯方式采用非阻塞式 I/O 模式,提升了系统吞吐和响应能力。
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:
资源类型 | 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 在市场上的垄断地位,推进云计算在朝着更加开放和可互操做的方向前进。