ceph的数据存储之路(10) -----ceph对象存储的ls命令实现及思考

更新:2016-10-19———————————————————————————————————————node

前面更新的内容可能略有偏颇,缘由是忘记了radow gateway这个东西,这对于对象存储很关键。通常的对象存储系统都不实现文件系统提供open、close、read、write和lseek等接口,对象存储有简单的接口,对应rest API风格,这也是本身近期经历一个rest API项目明白,rest API 类的接口只有简单的 get、put、delete等操做。这些操做不容许你针对一个对象进行部分获取,只能get整个object,修改后再上传到对象存储中。并且对象存储的使用场景特色来看,都是用于好比发布的微信状态、微博等,网站图片啊,一旦上传就不会修改,想要修改只能先删除,再从新发布。算法

包括以上的缘由等,使得对象存储不须要使用目录树来管理对象(文件系统是须要简历目录树的),从必定的角度来看,目前开源swift、ceph都没有使用目录树来管理对象,扁平的object管理模式,通常实在bucket或者pool中存放,ceph还涉及到pg层,因此通常对象存储使用2~3层的模式管理object,这在文件系统可了不起,在文件系统中的一个文件夹下文件数量超过一个值,会让整个文件夹性能降低的很是厉害,超多的文件inode会让内存等撑爆,这也是hdfs等不支持大量的小文件缘由,而对象存储ceph中,在一个pool中存储再多的文件数量对性能也不会太大的影响。swift

有人测试过对象存储和文件系统在同一个文件夹下存储文件,文件个数达到上亿后,文件系统完败,地址忘记了。。。。缓存

ceph对象存储网关会使用swift或s3 API来访问对象,这 个网关会本身维护一个索引,这个索引包含了object的一些信息,当用户使用ls命令时,网关会在本身维护的索引中进行查找,相比去查询文件系统的目录树,提升了不少的性能。ceph网关将本身的索引维护在一个叫作.rgw.buckets.index的pool中(为和普通的pool区分,这里叫作index pool),该index pool中对于其余正常的pool都会生成一个对象.dir.defaukt.xxxxx.x的object中,在该object的omap中会保存 正常pool中object的数据信息,这些信息保存在levelDB中,当ls时,直接从levelDB中获取,根本不须要遍历全部的object,一样swift 会将object维护在container中,因此对象存储在ls方面很快,可是若是在文件系统中,对于上亿个文件的文件夹中使用ls,那你可有得等了。微信

 

更新:2016-10-17———————————————————————————————————————分布式

以前本身 想不明白的问题,今天有了写想法,从新来讲说,这位大神问的问题:“你能说说ceph这种对象存储,ls命令是怎么实现的?对象存储能够保存大量的对象,怎么才能快速的ls出全部对象的信息?”函数

今天,有人问了我这个问题  https://www.oschina.net/question/252560_2201216,在回答问题前 我仔细的想了一下,为何ceph对象存储,ls命令能够快速列出全部对象的信息?平时咱们感受文件系统ls也很快啊,没感受有什么神奇的。因此没关注过。可是今天在这里重新说一下性能

为何会有对象存储? 一样都是文件,存在文件系统里不是同样的么?测试

这是由于当文件数目少时,他们差异不大,当存在大量的小文件时,好比淘宝的图片数据。海量图片文件。若是保存在文件系统中,你再去ls查看,会慢死。而对象存储中保存,使用ls会很是快速。网站

ls命令自己是查看文件元数据(文件大小,更新时间,属性等)的,在文件系统中,元数据和图片自己的数据在混在一块儿存储的,若是想要获取全部小文件的元数据,熟悉文件系统的朋友都知道,那但是费了劲儿,要处处找元数据所在的位置,遍历吧,因此时间会很长,慢死。可是在对象存储中不一样,元数据和图片数据分开保存,能够直接读取元数据,不用区分元数据和图片数据,因此对象存储很快。

今天明白了,仍是本身知道的太少,要多请教的。上面说的不恰当之处,请你们多加指点。

旧:—————————————————————————————————————————————

曾经被一个前辈问过:“你能说说ceph这种对象存储,ls命令是怎么实现的?对象存储能够保存大量的对象,怎么才能快速的ls出全部对象的信息?”

这个问题我不知道该怎么样来回答。脑子有点空白,这个问题是否是能够拆成以下两个问题:

问题1. 分布式对象存储和分布式文件系统存储相比较,当保存大量的对象文件或者文件时,对象存储的ls的速度要快,这是为何?

问题2. 分布式对象存储的ls实现与分布式文件系统的ls实现分别是什么样的?

 

回答:

对于问题1:

      我没有测试过,因此我也不知道谁更快。可是两者的数据都是在内存中,对象存储的这部分数据分散在不少的osd节点上,文件系统的这部分数据都保存在mds上。对于对象存储时能够将ls分明分红多个任务发送到不一样的osd上检索,最后合并结果。对于文件存储只能在mds单一节点上完成。这个是速度的关键么?若是有人懂得这个问题,请回答下,很是感谢。

对于问题2:

      ceph的对象存储检索方面,主要涉及到两点一个是rbd ls实现,一个是ceph ls实现。

rbd ls 实现比较简单,能够直接读取rbd_directory这个对象就能够了,该pool下面的全部的rbd都在这个对象文件中保存。

rbd命令从 rbd.cc中的main函数开始,开始解析命令,使用函数get_cmd。

2505:开始解析命令参数。

2508:是不是ls 或者list命令。

2510:在这里解析为 OPT_LIST。完成后再回到main函数中

3349:解析参数opt_cmd。

3351:case 解释参数OPT_LIST。

3353:若是是ls 或者list rbd的信息,这里直接调用do_list()函数。

0280:执行do_list函数。

0284:调用rbd.list() 获取全部的rbd名字,放在容器names中。

0199:执行rbd.list()函数。

0202:调用librbd::list()函数,继续获取rbd名字的列表。

0430:这里开始执行librbd::list()函数。

0436:读取指定的object,object的名字叫作RBD_DIRECTORY,这是个宏定义,解释出来就是rbd_directory文件。返回的结果保存在bl的buffer中。接下来在对bl中的数据进行解析出rbd name就好,而后将name所有都放在names中。返回结果。

 

总结rbd ls命令其实没有真正的去搜索全部的rbd名字,而是只读取了一个文件,就能够解析出全部的rbd名字列表。这个是否是快速的缘由呢?

 

若是不使用rbd形式,而是直接做为object存储呢? 可使用rados客户端或者网关实现对象文件的上传动做,须要把对象文件上传到指定的pool中。最终会根据对象文件的名字保存到一个pg中。由文件名字与pool的名字根据crush算法映射到一个pg中去,pg其实是一个文件夹,一个pg中的全部的object文件都保存在这个文件夹下。

因此 这里跟踪下“rados  –p testpool  ls“ 命令,看看如何ls出指定pool下面的对象文件。

命令开始于rados.cc中的main函数。该main函数中最后调用了rados_tool_common()来处理命令,继续看rados_tool_common中的处理。

1522:直接从这里开始看,前面都是参数解析和其余的操做。这里命令ls准备列举出全部的object对象。

1524:若是没有指定pool的名字,是返回错误的。因此你想ls出哪一个pool中的object。

1548:获取全部的object头部,而后从头部开始列出,输出到outstream中。这里是重点,后面继续描述。

1550:循环全部的object对象,而后将object对象的信息所有都输出到outstream中。

 

来看看在1524行的代码 io_ctx.nobjects_begin();这个函数是如何返回全部的object链。

1533:申明一个用于保存全部object的链 的头部listh。

1534:填充一些信息,用于获取object。

1535:声明一个object的迭代器。使用迭代器获取object。

1536:获取全部的object信息。而且保存。iter.get_next() -> impl->get_next()

0626:调用get_next函数,准备获取链表。

0636:调用rados_nobjects_list_next()开始获取。来到该函数中,查看下面的信息

3568:判断是否是链表是空的,这里空的表明以前没有获取过。

3569:这里调用librados::IoCtxImpl::nlist()函数。设定最大值等参数。

0366:设置最大的链表值。

0367:设置nspace的值。

0369:调用objecter->list_nobjects()函数,准备设置获取后的回调工做。

0371:加锁,等待完成操做唤醒。

0372:判断获取是否完成。

0373:等待获取完成,等待被唤醒。

0374:解锁操做。

 

接下来再看list_nobjects()中的一些处理状况。

3286:发送请求必须有一个objectoperation的op操做。

3287:设置对于pg的操做。主要的是为op添加一个操做,CEPH_OSD_OP_PGNLS。

3289:清空list列表的缓存信息。

3290:设置应答回调信息。这里是很是重要的一个设计。list_context是继续其余pg遍历的处理回调,onfinish是全部pg完成遍历的处理回调。后续会介绍下C_NList中的finsh函数的处理。

3291:设置object目标的定位信息。这里不是为了发送到某个object,而是发送到pg处理便可。

3293:开始设置设置读取current_pg中的object列表。这时 pool_id肯定,pg_id肯定,能够根据crush算法知晓current_pg所在osd-set的位置,而后选择一个osd进行读取,后续命令封装的过程就再也不详细解释了,拿着CEPH_OSD_OP_PGNLS标记直接去osd的代码中查看流程。

 

在replicatedPG.cc 中,函数do_pg_op()中会对CEPH_OSD_OP_PGNLS标记进行解释。case CEPH_OSD_OP_PGNLS。

0859:继续调用objects_list_partial进行处理。这个也是最重要的处理。

继续跟踪,来到代码的内部int PGBackend::objects_list_partial()

来到这里是否是就很是的明了呢?

0128:循环获取object,因为每次获取object的数量有限,能够分屡次完成。

0131:这里能够看的出,参数coll就是pg的目录,这个就是在扫描pg这个目录下的文件名字,而后看成是object,放在objects的结构中。这个扫描过程很简单了,继续向下的代码FileStore::collection_list_partial()中能够找到答案。因为目录内部的文件都已经创建了index,因此扫描起来也比较快。

 

还有一点须要说明的是,这只是获取其中一个pg的object信息,而后还须要处理其余的pg中object信息,对全部的object信息进行整合,返回给用户。何时开始处理的其余pg的object扫描呢?在读取pg的object时,设定了一个onack 回调函数,该函数具体由 list_nobjects()中申请的C_NList代替。这个C_NList的声明时使用了C_NList *onack = new C_NList(list_context, onfinish, this); C_NList继承自context类,因此它具备回调的属性。在C_NList中看如何回调的。

这个是C_NList设置的回调函数。这里有两个分支。参数r是本次处理结果是否正常。

1364:若是处理的结果正常,则须要继续处理扫描其余pg中的object信息。

1367:若是出现了错误等,则直接返回错误消息,再也不处理其余pg的object信息。

Objecter::_nlist_reply 函数中会从新调用list_nobjects(list_context, final_finish),继续扫描其余的pg的object信息。直到完成后,会调用final_finish->complete(0);这个在代码中很容易看到,既然全部的object都已经扫描完成后,还须要这个回调作什么?

 

还记得在librados::IoCtxImpl::nlist()函数。

0373:这里等待被唤醒,才能返回用户的请求线程继续处理。

因此须要在final_finish->complete(0);中实现对cond.wait 的唤醒操做。

这里的final_finish就是0369这里声明的C_SafeCond 回调,该回调中会唤醒0373行的等待,0373行被唤醒后继续执行,最后返回给使用命令ls的结果。

  

 

总结:

1.rbd ls 命令列举某个pool中的rbd。会直接读取pool中的rbd_directory对象文件,该文件中保存了该pool中的全部的rbd名字信息。

2.rados ls命令列举某个pool中的object。先找到pool,而且读出pool中pg的数量,而后再遍历每一个pg,读取每一个pg下面的object。合并结果就是全部的object。这个作法必须一个一个pg的去扫描,并不能作到并行扫描。

 

根据以上两点能够知晓,rbd ls的操做比较简单直接读取目标文件便可。rados ls的操做须要串行的扫描pool中的每一个pg中的object。

 

若是你问我rados ls这样的命令是怎么实现的,我能够讲述上面的实现的过程。

若是你问我对于文件系统的ls方式,我也能够讲述一下过程。

至于这两种方式的比较优点,还须要高人指点下,但愿你们不吝赐教。

相关文章
相关标签/搜索