QingStor 对象存储服务提供可无限扩展的存储空间、快速的数据存取性能、高度的可靠性和数据的安全性、细粒度的权限控制及简单易用的接口,以向广大用户提供廉价、可靠的存储系统。 本次分享,QingCloud 系统工程师 Osier 会分享青云QingCloud 对象存储的概念、实际的应用案例及进一步研发计划。
大家好,我是青云QingCloud 系统工程师 Osier Yang。今天我来和大家分享一些对象存储方面的内容。
“QingStor”为“青云对象存储”的项目及产品名称,为行文方便,下文将皆以“QingStor”代指“青云对象存储”。
今天交流内容包括:
我们从一个故事开始。在我们的对象存储研发后期,一个潜在客户来交流,他们想了解怎么用对象存储。交流期间,其中的技术负责人问了这样一个问题: “你们这既然是对象存储,那么它的类是怎么定义的?“。由此可见,即便是技术人员,也可能对”对象存储“产生误解。
所以要想讲清楚到底什么是”对象存储“,很有必要先解释“对象存储”这四个字,“存储”二字不必多说,凡 IT 从业者应该都理解,关键点是: 什么是“对象”?
Wikipedia 对“Object”分各领域做了解释(https://en.wikipedia.org/wiki/Object)。别的领域我们不管,我们只看哲学领域的定义,因为哲学领域的定义更具有普遍意义。Wikipedia 对“Object”在哲学领域的定义是:
a thing, being, or concept
在汉语里,和其英文本意最符合的词也就是”东西“了吧?百科里关于”东西“的释义如下:
泛指各种具体或抽象的人、事、物。例如:
在计算机领域,“对象”(Object)除了在面向对象编程用来表示一个类(Class)的实例(Instance)外,还被常用来表示一个变量(Variable),一个函数(Function),一个数据结构(Data Structure),一段在内存中的实体,等等,相信计算机领域的研发人员在各种各样的代码或工具里都见过。举个例子,Linux Kernel (Linux操作系统的核心)的模块名以“.ko”为后缀名,“ko”的全称为“Kernel Object”,这里的“Object”和 JAVA/C++ 语言里的“Object”显然不是一回事。
由此可见,在计算机领域,“对象” (Object)这个词也是一个泛指意义的词,其意义也可类比汉语中的“东西”。你可以指任何一个事物为“东西”,也即你可以指任何一个事物为“Object”。具体是什么“东西”,依场景不同而不同。至于到底“对象存储”里的“对象”是什么“东西”,请见后文。
要想理解什么是对象存储,我们从另外一个故事开始。企业 A 有一个应用,允许用户上传图片及视频,视频和图片的大小都比较小。
因为业务发展前期用户量很小,产生的数据量也足够小,最简单直接的方案为(实际生产中应该没人用这种方案,但最简单的方案往往更有助于我们看清问题本质):
这种最简单直接的方案几乎到处是缺点:
随着用户上传的数据量不断增加,我们假设容量率先增大了瓶颈,企业 A 为了解决容量问题,将存储架构改变为:
注:
* PV (LVM Physical Volume)
* VG (LVM Volume Group)
* LV (LVM Logical Group)
以上方案的利用 LVM 将众多硬盘空间抽象为一块大硬盘,突破了单个硬盘的容量限制,容量需求增加时,添加硬盘到 VG ,并对 LV 进行扩容即可。支持文件系统级别的 Snapshot , 可将数据回滚至某个点。但仍有缺陷:
假设企业 A 的存储容量需求在短时间内达不到单机的容量限制,但随着业务的发展,企业 A 开始重视数据的安全性。存储方案进一步演化为:
方案三引入了软 RAID 来做数据的冗余,同时保留了 LVM 带来了灵活性。但仍然有缺点:
我们假设企业 A 随着业务的进一步发展,存储容量需求在短时间内仍然达不到单机的容量限制,但开始重视服务的可靠性。故将存储方案进一步演化为:
此方案保留软 RAID 及 LVM 的同时,引入了 DRBD,通过网络来做块设备级别的复制,可靠性提高了一倍。但仍然有缺点:
随着业务的进一步发展,单机容量已无法满足企业A的存储需求。此时只剩下一条路:分布式存储。企业 A 不想投入人力自己开发分布式存储,而开源分布式存储方案繁多,经反复调研与测试,最终将方案确定为 HDFS :
HDFS的引入去除了单机容量的限制,但仍有缺陷:
“对象存储”来源于英文“Object Storage”或“Object-based Storage”。有人可能会想,照上文所述,那“Object Storage”岂不是该翻译为“东西存储”?如果谁这么翻译,告诉我,我家里的剑好久不用了。
翻译归翻译,术语归术语,都不妨碍我们将“Object Storage”理解为“存东西的存储”,那么“对象存储”存的到底是什么“东西”?
现在我们回顾一下企业A经历的存储方案历程,为了满足不断发展及增长的业务需求,企业 A 不断得在解决容量,数据安全,高可靠,可存储文件多少,读写性能等诸多问题,方案也变的越来越复杂。
像企业 A 这种有大量存储需求的企业不在少数,而不同企业,不同业务的数据特征千差万别。对象存储作为一种面向多租户的公共服务,除应该具备企业A的存储方案演变过程中不断追求的特性外,还应该通用,不能假设用户的数据特征(如类型,大小)。
我们先大致归纳一下对象存储应该有的特性:
前面我们以企业 A 的存储方案演进过程中所遇到的问题,归纳出了对象存储的大致目标,但还只局限于在数据存储层讨论。下面我们来看看索引层。
细心的同学可能已经发现,前文中我们一直在提一个问题:文件系统的限制。当存储的文件数目越来越多时,文件系统的目录树会变大,变深,读写性能会越来越差,inode 总数也可能达到限制。
文件系统层次的限制根源在于当前的文件系统的设计是为单机存储而设计的,树状的索引结构在非海量数据时代,很好的完成了数据索引的使命。但在面向海量存储时,就表现出了一些先天性问题,尤其面向海量小文件时。
避免文件系统面对海量数据时的缺陷可以有多种方案,其中最直接有效的方案是构建独立索引层,这样既能避免文件系统索引的问题,同时能利用文件系统的长久以来积累下来的优势。那么怎么设计独立索引层?如前所述,文件系统面对海量数据时的缺陷主要来自于树状索引结构,那新构建的独立索引层就应该将树状索引压扁,能压多扁压多扁,最终的索引结构如下 (其中 Bucket 这一级是不可避免的,无论如何,存储空间总是要区分开的)。
如上图所示,“Service”为顶层命名空间(Namespace),其下可有任意多个 Bucket (存储空间),Bucket 命名空间为第一级命名空间,其下可以有任意多 Object。
探讨完数据存储层及索引层,我们终于可以回到本节开头的问题了:“对象存储”的“对象”是个什么“东西”?
如果有人了解过文件系统的实现,定会发现文件系统的索引结构里包含了许多元信息,而对于对象存储系统而言,其中很多元信息无意义,我们创建了独立的索引层,自然也不想再带着这些无意义的元信息,我们希望独立的索引层存储的索引不多不少,足够精简,只保留基本且必须的元信息: 如 “类型”,“大小”,“校验值”,“最后修改时间”。
对于多数业务来说,基本的元信息已经足够,但对于某些业务而言,可能还需要更多的元信息。比如一个歌曲文件,除了类型、大小、校验值,最后修改时间,用户的业务还可能需要额外的描述,如:
如果对象存储的索引层能够允许用户自定义元数据。用户就不需要单独维护数据库去存储这些信息。
了解了”对象”(Object)的索引构成后,我们终于可以归纳一下”对象”(Object)”到底是什么”东西”了。
* 数据实体 (Data Entity)
* 数据实体的元数据 (Metadata)
* 数据实体的用户定义元数据 (User defined metadata)
下面是一个文件的元数据示例:
~
HTTP/1.1 200 OK
Server: QingStor
Date: Sun, 16 Aug 2015 09:05:00 GMT
Last-Modified: Fri, 14 Aug 2015 09:10:39 GMT
ETag: "0c2f573d81194064b129e940edcefe9b"
Content-Type: image/jpeg
Content-Length: 7987
Connection: close
Request-ID: aa08cf7a43f611e5886952542e6ce14
~
其中的“Last-Modified”, “Content-Type”, “Content-Type”, “ETag”(数据实体的 MD5 值)即为 QingStor 上一个“对象”(Object)的元信息。
每次交流时,都会有人问到对象存储相关的开源方案,问 Qingstor 为什么我们没有采取开源方案。我们在正式开发 QingStor 前,确实调研及测试过不少开源方案,但无一能够满足我们的目标。下面我们就选几个主流的开源方案探讨一下。
上面是 Openstack Swift 的架构图。下面是 Swift 的问题:
Ceph Radosgw 看起来很美好,但其糟糕的索引设计注定完全不能用于生产。这里不展开说了,感兴趣的可以看下面的链接:
https://github.com/ceph/ceph/pull/2187
Gluster 的设计非常工程派。无单独所应;未对文件进行任何切割或合并操作;所做的所有事情都是为了一个目的:一个更大的文件系统。
这种设计带来的问题是,它并未解决文件系统本身的限制,因为它未对文件系统的语义做任何修改。当存储海量小文件时,性能会变的很差,尽管 Gluster 为此做了各种优化(有兴趣的可以查找 Gluster 关于小文件读写性能优化的各种 translator ),但并不能改变其根本。
在章节“3”中我们逐步探讨了数据存储层,索引层,及对象。但为了循序渐进,企业A的存储演化过程中,我们刻意省略掉了一个组件: 接入层。
传统存储的访问接口各不相同。块存储暴露给用户的是一个一个的 Block 。文件系统或网络文件系统(如 NFS )暴露给用户的是 POSIX 文件系统接口。但无论是哪一种接口,都有一个共通的问题: 数据流转不便。
而对象存储通过将资源 URL 化,数据的流转方式就方便多了。
对象存储接收请求的协议为 HTTP ,所有一定有 HTTP Server ,接收到用户的文件上传和下载请求后,需要有相应的处理方法。且作为面向多租户的公有服务,无法假设用户的请求行为,所有用户加起来的并发请求可能会很大。另外,接入层得高可用。所以得引入负载均衡。
我们把最前端的负载均衡,后端的 HTTP Server ,及各种处理方法,统称为接入层。接入层作为QingStor的最外层建筑,向用户暴露 RESTful 的 API 。
青云QingCloud IaaS 服务为多区域部署,用户可根据自己的需求选择适合自己的区域部署服务。而 QingStor 作为存储服务,不应该远离计算资源(简单计算资源如主机,复杂计算资源如 QingCloud 的大数据平台, Spark、Storm、 Hadoop、etc)。所以我们把决定权交给了用户,由用户决定如何部署计算及存储资源。
QingStor 的多区域部署示意图如下:
为了进一步拉近计算与存储的距离。同一区域的计算资源访问 QingStor 走内部网络。
文中已分别就“接入层”,“索引层”,及“数据存储层”进行了探讨。这里进一步阐述一下QingStor架构设计的核心思想:
各层次的具体设计如下:
“接入层”,“索引层”,及“数据层”构成了QingStor的架构主干。此外,还有“调度器”,”监控服务“,及异步服务如“垃圾回收”,“文件合并”,“碎片整理”等。
除 API 及用户指南文档外,目前我们支持 Python SDK,控制台图形化界面,命令行工具:
HDW(Hash Data Warehouse)是由北京酷克数据科技有限公司开发,类似 AWS Redshift 的云端数据仓库服务,产品将于今年 3 月底在青云QingCloud 上线。
HDW 基于 Greenplum Database ,为云计算平台做了大量的系统架构及工程优化。除了具有快速部署,简单易用和零前期投入(按使用量收费)等商业优势外,还有如下技术优势:
下面演示 HDW 如何与 QingStor 集成。在这个演示中,我们将把数据从 QingStor 中导入到数据仓库,并将最终的查询结果回导至 QingStor 。
创建一个Bucket,名为”hdw-hashdata-cn”,并在其下创建两个目录“input”和”output”。
在本地创建文件 “persons.txt” 和 “orders.txt”,并将其上传至前面创建的 Bucket “hdw-hashdata-cn” 的 “input”目录里。
“persons.txt”内容:
~
1,Adams,John,Oxford Street,London
2,Bush,George,Fifth Avenue,New York
3,Carter,Thomas,Changan Street,Beijing
~
orders.txt 内容
~
1,77895,3
2,44678,3
3,22456,1
4,24562,1
5,34674,65
~
连接 HDW 数据仓库进入 Postgres 数据库,执行如下图所示命令创建相应的数据表(请将里面的 access_key_id 和 secret_access_key 换成你的 API 密钥)。
外部表 e_persons 对应前面上传的 persons.txt 文件,e_orders 对应 orders.txt 文件,e_result 对应 Bucket hdw-hashdata-cn 的 output 目录。
执行如下命令将数据从外部表(对应青云对象存储的 input 目录)导入到数据仓库中:
此时,可以看到 output 目录下多了两个文件(这是因为演示系统中用了两个 workers ,每个 worker 往外写一个文件对象):gpqsext.0.0 和 gpqsext.1.0 。
下载 gpqsext.0.0 和 gpqsext.1.0 ,查看内容:
在这个例子中,我们演示了如何将数据从 QingStor 里导入到 HDW 数据仓库中,并将查询结果回导至青云对象存储里。基于这两个基本功能,我们可以构建更复杂的数据仓库管理功能,如在数据仓库空闲的时候,将元数据和用户数据备份到对象存储中,释放计算资源和存储资源,节省成本;当下次需要的时候,利用备份到对象存储中的数据恢复数据仓库,继续正常使用。
各种 Feature 这里就不多说了,主要说一下两个大个方向。
第一个方向面向性能。纵然我们在系统架构设计时就在各方面考虑了性能,比如多区域部署,同区域计算资源内网访问 QingStor。但为了应对更加复杂的场景,我们在性能方面会同时兼顾内外网。内网方面,我们在做内网加速,外网方面我们在做 CDN 。两者将兼于近期上线。
第二个方向面向数据处理。QingStor 作为海量数据存储池,将会与青云QingCloud 平台上的计算资源紧密整合,尤其是青云QingCloud 大数据平台,如 Hadoop、Spark、 Storm 等。同时我们非常欢迎第三方数据处理服务在青云QingCloud 平台上构建服务,如第 7 章节中的 HDW。
另外,我们也将开发一些特定的数据处理服务,比如图形图像处理,音视频处理等。
我的分享就到此结束,谢谢大家,谢谢北京酷克数据科技有限公司提供的 HDW 案例。
1、存储超过一定规模有好的性能解决方案吗?
答:这个问题不具体。所以我也只能不具体的回答。
存储是计算机里在时间和空间两个维度上冲突最为严重的组件。在存储系统的设计过程中,往往会顾此失彼。之前我在其它场合分享时曾经说过,QingStor的一个很重要的设计思想是: 折衷。也即大家常说的tradeoff,事实上tradeoff会出现在各种各样的场景里,甚至在一个函数的设计里都会体现。但据我个人经验,tradeoff在存储领域体现最为明显。
2、QingStor 有什么前端方案吗,方便集成在应用里。
答:没有特别理解。但应用可以直接调用QingStor的API。如文中所述,当前我们支持Python语言的SDK,接下来会支持其他主流语言的SDK。届时可直接使用。
3、我觉得 AWS 的 lambda 服务很好,青云有类似的打算么?
答:这个问题很好。说明提问者对云服务非常了解。事实上春节期间我们已经设计了一版草案,关于青云平台上的异步事件驱动的服务框架如何构建。由于QingStor是青云QingCloud众多服务中第一个对异步事件驱动的框架有明确需求的服务,所以该框架会融合在QingStor的研发进程中来实现。我们计划是下月或者5月份开始此事件驱动的框架研发。初步规划是,先构建异步事件框架,以开发外围服务,如图形图像处理。然后进一步抽象出类似于lambda的服务。
4、青云QingCloud 的对象存储技术对于既有数据百亿级,日产生新数据 5000 万到 2 亿的高写入并发,相对较低的查询并发场景下有什么方案?
答:并发的提升涉及到系统的各层次,和许多因素有关。这个简单说几个方面。1)存储服务有一个特性:数据流和控制流很难分离,对于对象存储尤其如此。所以对于对象存储系统而言要尽量减少数据传输过程中的中转;2) 扩大接入层的集群规模;3) 优化接入层的网络链路,比如尽量不走Linux kernel的TCP/IP协议栈;4) 利用缓存和队列缓冲数据的写入量。
5、单 Accout 支持多少桶,多少对象,存储空间?
答:初始状态限制2个存储空间,如果有需要可以提工单提高。如分享中所说,对象数量没有限制。
6、对象副本是多少或 EC 配比
答:是三副本,目前还不支持纠删码。纠删码的支持也是我们今年要做的Feature之一。