1.前景提要
- Ceph是个分布式对象系统,具有对象存储的特征,具备存储海量非结构化数据的能力。
- Ceph核心模块RADOS是一个基于对象的存储系统,通常情况下应用通过RADOS抽象库librados提供的对象接口访问RADOS集群,但是librados只提供了私有接口,不支持访问HTTP协议访问。
- Ceph为了支持通用的HTTP接口设计了RGW系统(RADOS GateWay,即对象存储网关)。然而,如果RGW只提供通用的HTTP访问接口,应用就需要花费较大的代价才能开发出适配RGW访问接口的软件,这不利于Ceph在云存储中迅速普及,因此RGW选择适配云存储领域应用最广的Amazon S3和OpenStack Swift接口,使得现有的S3和Swift用户可以以很小代价接入对象存储系统中。
- 下文主要偏向于描述Amazon S3接口
2.总体架构
对象存储最常见的应用为互联网应用,互联网应用的主要特点是数据存储位置不一定在本地或局域网内,数据经过Internet(基于HTTP协议)传输,存储在任意一个网络能到达的地方。Ceph设计的RGW存储网关系统支持HTTP访问接口,兼容Amazon S3的接口和OpenStack Swift的接口
RGW作为对象储存网关系统,一方面扮演着RADOS集群的客户端角色,为对象存储的应用提供数据存储的通道;另一方面又扮演者HTTP的服务端角色,接受并且解析互联网传送过来的数据。
3.对象存储系统的基础数据实体
用户(user)、存储桶(bucket)、对象(object)
3.1.用户(user):
用户就是指对象存储的使用者了,一个用户可以拥有一个或者多个存储桶
- Amazon S3的基础数据实体包含user,bucket,object,与以上完全对应;OpenStack Swift将用户的概念分为了account和user,其中account对应一个项目或者租户,每个account可以被多个user共享,其他基础实体基本概念相同。
- 虽然这里主要谈到Amazon S3接口,但是RGW为了兼容Amozon S3和OpenStack Swift接口,在设计上必须兼容两者设计的概念。因此将用户分为用户(user)和子用户(subuser),其中用户对应S3的用户,Swift的子用户。
- 用户管理设计主要基于以下几个方面考虑:1.为了RESTful API进行请求认证;2.为了控制用户对资源的访问权限;3.为了控制用户的利用存储空间。因此,一个用户包含的信息包括用户认证信息,访问控制权限信息和配额信息。
S3用户身份认证机制都是基于**认证的。认证过程如下:
- 发送请求前,使用用户私有**(secret_key),请求内容等,采用与RGW网关约定好的算法计算出数字签名后,将数字签名以及用户访问**(access_key)封装在请求中发送给RGW网关
- RGW网关收到请求后,使用用户访问**作为索引从RADOS集群中读取用户信息,并从用户信息中获取用户私有**
- 使用用户私有**,请求内容等,采用与应用约定好的算法计算数字签名
- 判断RGW生成的数字签名和请求的前面是否匹配,匹配则用户通过验证
但是身份验证请求过后,并不意味着用户具有操作资源(bucket,对象等)的权限。
针对不同资源的访问,用户必须具备相应的访问权限才能访问对应的资源。对于每个请求,首先检查用户对资源是否具有对应的访问权限,包括read,write,delete分别代表读,写,删除权限,比如只有具有写权限的用户才能创建存储桶。
此外,为了防止某些用户占用太多存储空间导致其他用户无空间使用,以及方便根据用户付费情况给不同用户配置不同的存储空间,RGW允许对用户进行配额限制并且在用户上传/删除对象时做配额检查。
综上分析,一个用户所包含的关键信息包含用户认证需要的用户ID、**信息、控制资源访问需要用到用户权限信息以及用户配额信息。RGW使用数据结构RGWUserInfo管理用户信息。
就是这样RGW将用户信息把保存在RADOS对象的数据部分,一个用户对应一个RADOS对象。由于大部分情况下我们需要使用用户ID作为索引获取用户信息,因此该对象以用户ID命名(RADOS通过‘‘pool名+对象’’来查询一个对象,后面解释pool)。
RGW需要将访问**,子用户,email和用户信息所在的RADOS对象建立索引关系,针对这种情况,RGW采用了二级索引的实现方式。即分别创建以用户访问**、子用户、email命名的三个RADOS对象(以下称索引对象),并且将用户ID保存在对象的数据部分。从而当需要使用某个索引查询用户信息时,首先从索引对象读出用户ID,然后使用用户ID作为索引读取用户信息。
3.2存储桶:
存储桶是对象的容器。一个存储桶对应一个RADOS对象。
一个存储桶包含的信息分为两类:
- 一类是对象RGW网关透明的信息,这类信息通常指用户自定义的元数据,RGW将这些信息保存在对象的扩展信息中,一个KV键值对对应一个扩展属性条目;
- 一类是RGW网关关注的信息,包括存储桶中对象的存储策略,存储桶中索引对象的数目以及应用对象与索引对象的映射关系、存储桶的配额等,这类信息由数据结构RGWBucketInfo管理,保存在RADOS对象的数据部分。
创建存储桶时,RGW网关会同步创建一个或多个索引对象,用于保存改存储桶下的对象列表,以支持查询存储桶对象列表(List Bucket)功能,因此在存储桶中有新的对象上传或者删除时必须更新索引对象。
RGW采用了Ceph通常采用的解决方案,将索引对象分片(shard),把一个索引对象切分成多个对象,不同应用对象记录在不同的索引对象上。
这个方案极大的改观了对象的写性能,但是分片后带来的一个负面影响,会影响查询桶对象列表操作的性能。分片后原先只需要读一个索引对象就可以获取存储桶下对象列表变成了针对多个索引对象的读,这时,RGW网关与RADOS集群间的网络延时,多个索引对象查询结果的合并对查询存储桶对象列表性能产生很大的影响。
为了降低这个负面影响,RGW视图对多个索引对象并发读取代串行读,以降低查询存储桶对象列表操作的处理时间。但事物都有两面性,如果一味的增加索引对象的数目,与此同时归并排序所消耗的计算量和缓存也会增加,从而也制约了查询效率。
3.3对象:
对象是对象存储系统数据组织和存储的基本单位,一个对象包含数据和元数据。数据指的是用户保存的真正的数据,比如一个文本文件的内容或者一个视频文件的内容;元数据指的是除了数据外的其他需要保存的信息,一般由KV键值对组成。(类似于创建桶时的两类信息)
与文件系统层级管理结构不同,对象存储系统中所有对象都以扁平方式存储,对象之间没有直接关联,这种特性很容易实现将不同的对象保存在不同的物理位置。此外,对象存储不提供编辑对象部分内容的功能,对象必须作为一个整体单元操作,即使只更新对象中的一个字符,也必须将整个对象从云端下载下来,更新后上传。
应用上传的对象包括数据和元数据两部分,数据部分保存在一个或者多个RADOS对象的数据部分,元素据保存在其中一个RADOS对象的扩展属性中。(为什么前面时一个或多个呢?因为前面提到的分片)
RGW对于单个对象提供了两种上传接口:整体上传和分段上传
3.3.1整体上传:
RGW限制了整体上传一个对象器大小不能大于5GB,当用户上传的对象大于该限制时必须分段上传,否则上传对象失败。为了更好理解用户上传对象和RADOS对象的对应关系,先了解两个值和一个类:
rgw_max_chunk_size:该宏值用来表示RGW下发到RADOS集群单个I/O的大小,同时决定应用对象分成多个RADOS对象时首对象的大小,以下简称分块大小
rgw_obj_stripe_size:公司宏值用来指定当一个对象被分成多个RADOS对象时中间对象的大小,以下简称条带大小
Class RGWWObjManifest:用来管理用户上传的对象和RADOS对象的对应关系,以下简称manifest
整体上传时,当对象小于分块时,用户上传的一个对象只对应一个RADOS对象,该RADOS对象以应用对象名称命名,对象元数据也保存在该RADOS对象的扩展属性中;当用户上传的对象大于分块时,被分解成一个大小等于分块大小的首对象,多个大小等于条带大小的中间对象,和一个大小小于条带大小的尾对象。
3.3.2分段上传:
分段上传对象时,RGW网关按照条带大小将每个分段分成多个RADOS对象。当所有的分段上传结束以后,RGW会另外生成一个RADOS对象,用于保存应用对象元数据和所有分段的manifest。
4.数据存储位置
前面分析了RGW数据的组织和存储方式,不同的用户数据最终以RADOS对象为单位保存到了RADOS集群中。为了实现不同的应用数据存储位置的隔离,RGW使用zone来管理用户数据的存储位置,zone由一组存储池(pool)组成,不同存储池用来保存不同的数据,RGW使用数据结构RGWZoneParams来管理不同的存储池。因此配置一个RGW实例时,需要指定该RGW实例所属的zone以及确定数据的存储位置。
需要重点强调的是placement_pools字段。该字段由map<string,RGWZonePlacementInfo>组成,string是一个自定义字符串,可以认为是一个对象存储策略 ,用来唯一定位第二个字段RGWZonePlacementInfo。第二个字段主要定义应用对象的存储位置、用户分段上传对象时的中间数据的存储位置和存储索引对象的存储位置等。当创建一个存储桶时,用户可以显式指定zone中已存在的存储策略,后续往存储桶中上传对象时,将按照该存储策略存储对象。