欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > PDF文档下载
     

    Ceph源码分析.html.pdf

    • 资源ID:5519049       资源大小:1.23MB        全文页数:29页
    • 资源格式: PDF        下载积分:6
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要6
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Ceph源码分析.html.pdf

    序言 自从2013年加入Ceph社区以来,我一直想写一本分析Ceph源码的书,但是两年多来提交了数万行的代码后,我渐渐放下了这个事情。Ceph每个月、每周都会发生巨大变化,我总是想让Ceph源码爱好者 看到最新最棒的设计和实现,社区一线的模块维护和每周数十个代码提交集的阅读,让我很难有时间回顾和把握其他Ceph爱好者的疑问和需求点。 今天看到这本书让我非常意外,作者常涛把整个Ceph源码树肢解得恰到好处,如庖丁解牛般将Ceph的核心思想和实现展露出来。虽然目前Ceph分分钟都有新的变化,但无论是新的模块设计,还是重构 已有逻辑,都是已有思想的翻新和延续,这些才是众多Ceph开发者能十年如一日改进的秘密! 我跟作者常涛虽然只有一面之缘,但是在开源社区中的交流已经足够成为彼此的相知。他对于分布式存储的设计和实现都有独到见解,其代码阅读和理解灵感更是超群。我在年前看到他一些对Ceph核 心模块的创新性理解,相信这些都通过这本书展现出来了。 这本书是目前我所看到的从代码角度解读Ceph的最好作品,即使在全球范围内,都没有类似的书籍能够与之媲美。相信每个Ceph爱好者都能从这本书中找到自己心中某些疑问的解答途径。 作为Ceph社区的主要开发者,我也想在这里强调Ceph的魅力,希望每个读者都能充分感受到Ceph社区生机勃勃的态势。Ceph是开源世界中存储领域的一个里程碑!在过去很难想像,从IT巨无霸们组成 的巨大存储壁垒中能够诞生一个真正被大量用户使用并投入生产环境的开源存储项目,而Ceph这个开源存储项目已经成为全球众多海量存储项目的主要选择。 众所周知,在过去十年里,IT技术领域中巨大的创新项目很多来自于开源世界,从垄断大数据的Hadoop、Spark,到风靡全球的Docker,都证明了开源力量推动了新技术的产生与发展。而再往以前看十 年,从Unix到Linux,从Oracle到MySQL/PostgreSQL,从VMWare到KVM,开源世界从传统商业技术继承并给用户带来更多的选择。处于开源社区一线的我欣喜地看到,在IT基础设施领域,越来越多的创业 公司从创立之初就以开源为基石,而越来越多的商业技术公司也受益于开源,大量的复杂商业软件基于开源分布式数据库、缓存存储、中间件构建。相信开源的Ceph也将成为IT创新的驱动力。正如Sage Weil在2016 Ceph Next会议上所说,Ceph将成为存储里的Linux! 王豪迈,XSKY公司CTO 2016年9月8日 前言 随着云计算技术的兴起和普及,云计算基石:分布式共享存储系统受到业界的重视。Ceph以其稳定、高可用、可扩展的特性,乘着开源云计算管理系统OpenStack的东风,迅速成为最热门的开源分布式 存储系统。 Ceph作为一个开源的分布式存储系统,人人都可以免费获得其源代码,并能够安装部署,但是并不等于人人都能用起来,人人都能用好。用好一个开源分布式存储系统,首先要对其架构、功能原理等 方面有比较好的了解,其次要有修复漏洞的能力。这些都是在采用开源分布式存储系统时所面临的挑战。 要用好Ceph,就必须深入了解和掌握Ceph源代码。Ceph源代码的实现被公认为比较复杂,阅读难度较大。阅读Ceph源代码,不但需要对C+语言以及boost库和STL库非常熟悉,还需要有分布式存储系 统相关的基础知识以及对实现原理的深刻理解,最后还需要对Ceph框架和设计原理以及具体的实现细节有很好的把握。所以Ceph源代码的阅读是相当有挑战性的。 本着对Ceph源代码的浓厚兴趣以及实践工作的需要,需要对Ceph在源代码层级有比较深入的了解。当时笔者尽可能地搜索有关Ceph源代码的介绍,发现这方面的资料比较少,笔者只能自己对着Ceph源 代码开始了比较艰辛的阅读之旅。在这个过程中,每一个小的进步都来之不易,理解一些实现细节,都需要对源代码进行反复地推敲和琢磨。自己在阅读的过程中,特别希望有人能够帮助理清整体代码的 思路,能够解答一下关键的实现细节。本书就是秉承这样一个简单的目标,希望指引和帮助广大Ceph爱好者更好地理解和掌握Ceph源代码。 本书面向热爱Ceph的开发者,想深入了解Ceph原理的高级运维人员,想基于Ceph做优化和定制的开发人员,以及想对社区提交代码的研究人员。官网上有比较详细的介绍Ceph安装部署以及操作相关的 知识,希望阅读本书的人能够自己动手实践,对Ceph进一步了解。本书基于目前最新的Ceph 10.2.1版本进行分析。 本书着重介绍Ceph的整体框架和各个实现模块的实现原理,对核心源代码进行分析,包括一些关键的实现细节。存储系统的实现都是围绕数据以及对数据的操作来展开,只要理解核心的数据结构,以 及数据结构的相关操作就可以大致了解核心的实现和功能。本书的写作思路是先介绍框架和原理,其次介绍相关的数据结构,最后基于数据结构,介绍相关的操作实现流程。 最后感谢一起工作过的同事们,同他们在Ceph技术上进行交流沟通并加以验证实践,使我受益匪浅。感谢机械工业出版社的编辑吴怡对本书出版所做的努力,以及不断提出的宝贵意见。感谢我的妻子 孙盛南女士在我写作期间默默的付出,对本书的写作提供了坚强的后盾。 由于Ceph源代码比较多,也比较复杂,写作的时间比较紧,加上个人的水平有限,错误和疏漏在所难免,恳请读者批评指正。有任何的意见和建议都可发送到我的邮箱changtao381163.com,欢迎读者 与我交流Ceph相关的任何问题。 常涛 2016年6月于北京 第1章 Ceph整体架构 本章从比较高的层次对Ceph的发展历史、Ceph的设计目标、整体架构进行简要介绍。其次介绍Ceph的三种对外接口:块存储、对象存储、文件存储。还介绍Ceph的存储基石RADOS系统的一些基本概 念、各个模块组成和功能。最后介绍了对象的寻址过程和数据读写的原理,以及RADOS实现的数据服务等。 1.1 Ceph的发展历程 Ceph项目起源于其创始人Sage Weil在加州大学Santa Cruz分校攻读博士期间的研究课题。项目的起始时间为2004年,在2006年基于开源协议开源了Ceph的源代码。Sage Weil也相应成立了 Inktank公司专注于Ceph的研发。在2014年5月,该公司被Red Hat收购。Ceph项目的发展历程如图1-1所示。 2012年,Ceph发布了第一个稳定版本。2014年10月,Ceph开发团队发布了Ceph的第七个稳定版本Giant。到目前为止,社区平均每三个月发布一个稳定版本,目前的最新版本为10.2.1。 图1-1 Ceph的发展历程 1.2 Ceph的设计目标 Ceph的设计目标是采用商用硬件(Commodity Hardware)来构建大规模的、具有高可用性、高可扩展性、高性能的分布式存储系统。 商用硬件一般指标准的x86服务器,相对于专用硬件,性能和可靠性较差,但由于价格相对低廉,可以通过集群优势来发挥高性能,通过软件的设计解决高可用性和可扩展性。标准化的硬件可以极大地 方便管理,且集群的灵活性可以应对多种应用场景。 系统的高可用性指的是系统某个部件失效后,系统依然可以提供正常服务的能力。一般用设备部件和数据的冗余来提高可用性。Ceph通过数据多副本、纠删码来提供数据的冗余。 高可扩展性是指系统可以灵活地应对集群的伸缩。一般指两个方面,一方面指集群的容量可以伸缩,集群可以任意地添加和删除存储节点和存储设备;另一方面指系统的性能随集群的增加而线性增 加。 大规模集群环境下,要求Ceph存储系统的规模可以扩展到成千上万个节点。当集群规模达到一定程度时,系统在数据恢复、数据迁移、节点监测等方面会产生一系列富有挑战性的问题。 1.3 Ceph基本架构图 Ceph的整体架构由三个层次组成:最底层也是最核心的部分是RADOS对象存储系统。第二层是librados库层;最上层对应着Ceph不同形式的存储接口实现,架构如图1-2所示。 图1-2 Ceph基本架构图 Ceph的整体架构大致如下: ·最底层基于RADOS(reliable,autonomous,distributed object store),它是一个可靠的、自组织的、可自动修复、自我管理的分布式对象存储系统。其内部包括ceph-osd后台服务进程和ceph-mon监控进 程。 ·中间层librados库用于本地或者远程通过网络访问RADOS对象存储系统。它支持多种语言,目前支持C/C+语言、Java、Python、Ruby和PHP语言的接口。 ·最上层面向应用提供3种不同的存储接口: ·块存储接口,通过librbd库提供了块存储访问接口。它可以为虚拟机提供虚拟磁盘,或者通过内核映射为物理主机提供磁盘空间。 ·对象存储接口,目前提供了两种类型的API,一种是和AWS的S3接口兼容的API,另一种是和OpenStack的Swift对象接口兼容的API。 ·文件系统接口,目前提供两种接口,一种是标准的posix接口,另一种通过libcephfs库提供文件系统访问接口。文件系统的元数据服务器MDS用于提供元数据访问。数据直接通过librados库访问。 1.4 Ceph客户端接口 Ceph的设计初衷是成为一个分布式文件系统,但随着云计算的大量应用,最终变成支持三种形式的存储:块存储、对象存储、文件系统,下面介绍它们之间的区别。 1.5 RADOS RADOS是Ceph存储系统的基石,是一个可扩展的、稳定的、自我管理的、自我修复的对象存储系统,是Ceph存储系统的核心。它完成了一个存储系统的核心功能,包括:Monitor模块为整个存储集 群提供全局的配置和系统信息;通过CRUSH算法实现对象的寻址过程;完成对象的读写以及其他数据功能;提供了数据均衡功能;通过Peering过程完成一个PG内存达成数据一致性的过程;提供数据自动 恢复的功能;提供克隆和快照功能;实现了对象分层存储的功能;实现了数据一致性检查工具Scrub。下面分别对上述基本功能做简要的介绍。 1.6 本章小结 本章介绍了Ceph的系统架构,通过本章,可以对Ceph的基本架构和各个模块的组件有了整体的了解,并对一些基本概念及读写的原理、各个数据功能模块有了大致了解。 本章介绍的Ceph客户端的基本概念,在第5章会详细介绍到。本章介绍的对象寻址的CRUSH算法将会在第4章详细介绍到。在本章介绍的本地对象存储将会在第7章详细介绍到。本章介绍的数据读写流 程,将会在第6章详细介绍。本章介绍的纠删码将在第8章中详细介绍。本章介绍的快照和克隆将在第9章详细介绍。本章介绍的Ceph Peering的过程将会在第10章详细介绍。本章介绍的数据恢复和回填将会 在第11章介绍到。本章介绍的Ceph Srcub机制将会在第12章详细介绍。本章介绍的Cache Tier将在第13章详细介绍。 第2章 Ceph通用模块 本章介绍Ceph源代码通用库中的一些比较关键而又比较复杂的数据结构。Object和Buffer相关的数据结构是普遍使用的。线程池ThreadPool可以提高消息处理的并发能力。Finisher提供了异步操作时来执 行回调函数。Throttle在系统的各个模块各个环节都可以看到,它用来限制系统的请求,避免瞬时大量突发请求对系统的冲击。SafteTimer提供了定时器,为超时和定时任务等提供了相应的机制。理解这些数 据结构,能够更好理解后面章节的相关内容。 2.1 Object 对象Object是默认为4MB大小的数据块。一个对象就对应本地文件系统中的一个文件。在代码实现中,有object、sobject、hobject、ghobject等不同的类。 结构object_t对应本地文件系统的一个文件,name就是对象名: struct object_t string name; http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/ sobject_t在object_t之上增加了snapshot信息,用于标识是否是快照对象。数据成员snap为快照对象的对应的快照序号。如果一个对象不是快照对象(也就是head对象),那么snap字段就被设置为 CEPH_NOSNAP值。 struct sobject_t object_t oid; snapid_t snap; http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/ hobject_t是名字应该是hash object的缩写。 struct hobject_t object_t oid; snapid_t snap; private: uint32_t hash; bool max; uint32_t nibblewise_key_cache; uint32_t hash_reverse_bits; public: int64_t pool; string nspace; private: string key; http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/ 其在sobject_t的基础上增加了一些字段: ·int64_t pool:所在的pool的id。 ·string nspace:nspace一般为空,它用于标识特殊的对象。 ·string key:对象的特殊标记。 ·string hash:hash和key不能同时设置,hash值一般设置为就是pg的id值。 ghobject_t在对象hobject_t的基础上,添加了generation字段和shard_id字段,这个用于ErasureCode模式下的PG: ·shard_id用于标识对象所在的osd在EC类型的PG中的序号,对应EC来说,每个osd在PG中的序号在数据恢复时非常关键。如果是Replicate类型的PG,那么字段就设置为NO_SHARD(-1),该字段对于 replicate是没用。 ·generation用于记录对象的版本号。当PG为EC时,写操作需要区分写前后两个版本的object,写操作保存对象的上一个版本(generation)的对象,当EC写失败时,可以rollback到上一个版本。 struct ghobject_t hobject_t hobj; gen_t generation; shard_id_t shard_id; bool max; public: static const gen_t NO_GEN = UINT64_MAX; http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/http:/www.hzcourse.com/resource/readBook?path=/openresources/teach_ebook/uncompressed/15932/OEBPS/Text/ 2.2 Buffer Buffer就是一个命名空间,在这个命名空间下定义了Buffer相关的数据结构,这些数据结构在Ceph的源代码中广泛使用。下面介绍的buffer:raw类是基础类,其子类完成了Buffer数据空间的分 配,buffer:ptr类实现了Buffer内部的一段数据,buffer:list封装了多个数据段。 2.3 线程池 线程池(ThreadPool)在分布式存储系统的实现中是必不可少的,在Ceph的代码中广泛用到。Ceph中线程池的实现也比较复杂,结构如下: class ThreadPool : public md_config_obs_t CephContext *cct; string name; /线程池的名字 string lockname; /锁的名字 Mutex _lock; /线程互斥的锁,也是工作队列访问互斥的锁 Cond _cond; /锁对应的条件变量 bool _stop; /线程池是否停止的标志 int _pause; /暂时中止线程池的标志 int _draining; Cond _wait_cond; int ioprio_class, ioprio_priority; vector work_queues; /工作队列 int last_work_queue; /最后访问的工作队列 set _threads; /线程池中的工作线程 list _old_threads; /等待进joined操作的线程 int processing; 类ThreadPool里包函一些比较重要的数据成员: ·工作线程集合_threads。 ·等待Join操作的旧线程集合_old_threads。 ·工作队列集合,保存所有要处理的任务。一般情况下,一个工作队列对应一个类型的处理任务,一个线程池对应一个工作队列,专门用于处理该类型的任务。如果是后台任务,又不紧急,就可以将 多个工作队列放置到一个线程池里,该线程池可以处理不同类型的任务。 线程池的实现主要包括:线程池的启动过程,线程池对应的工作队列的管理,线程池对应的执行函数如何执行任务。下面分别介绍这些实现,然后介绍一些Ceph线程池实现的超时检查功能,最后介绍 ShardedThreadpool的实现原理。 2.4 Finisher 类Finisher用来完成回调函数Context的执行,其内部有一个FinisherThread线程来用于执行Context回调函数: class Finisher vector finisher_queue; / 需要执行的Contex,成功返回值为0 list finisher_queue_rval; 、 / 需要执行的Context,返回值为int类型的有效值 2.5 Throttle 类Throttle用来限制消费的资源数量(也常称为槽位“slot”),当请求的slot数量达到max值时,请求就会被阻塞,直到有新的槽位释放出来,代码如下: class Throttle CephContext *cct; const std:string name; PerfCounters *logger; ceph:atomic_t count, max; / count:当前占用的slot的数量 / max:sloct数量的最大值 Mutex lock; /等待的锁 list cond; /等待的条件变量 函数get用于获取数量为c个slot,参数c默认为1,参数m默认为0,如果m不为默认的0值,就用m值重新设置slot的max值。如果成功获取数量为c个slot,就返回true,否则就阻塞等待。例如: bool Throttle:get(int64_t c, int64_t m) 函数get_or_fail当获取不到数量为c个slot时,就直接返回false,不阻塞等待: bool Throttle:get_or_fail(int64_t c) 函数put用于释放数量为c个slot资源: int64_t Throttle:put(int64_t c) 2.6 SafeTimer 类SafeTimer实现了定时器的功能,代码如下: class SafeTimer CephContext *cct; Mutex Cond cond; bool safe_callbacks; /是否是safe_callbacks SafeTimerThread *thread; /定时器执行线程 std:multimap schedule; /目标时间和定时任务执行函数Context std:map:iterator events; /定时任务定时任务在shedule中的位置映射 bool stopping; /是否停止 添加定时任务的命令如下: void SafeTimer:add_event_at(utime_t when, Context *callback) 取消定时任务的命令如下: bool cancel_event(Context *callback); 定时任务的执行如下: void SafeTimer:timer_thread() 本函数一次检查scheduler中的任务是否到期,其循环检查任务是否到期执行。任务在schedule中是按照时间升序排列的。首先检查,如果第一任务没有到时间,后面的任务就不用检查了,直接终止 循环。如果第一任务到了定时时间,就调用callback函数执行,如果是safe_callbacks,就必须在获取lock的情况下执行Callback任务。 2.7 本章小结 本章介绍了src/common目录下的一些公共库中比较常见的类的实现。BufferList在数据读写、序列化中使用比较多,它的各种不同成员函数的使用方法需要读者自己进一步了解。对于 ShardedThreadPool,本章只介绍了实现的原理,具体实现在不同的场景会有不同,需要读者面对具体的代码自己去分析。 第3章 Ceph网络通信 本章介绍Ceph网络通信模块,这是客户端和服务器通信的底层模块,用来在客户端和服务器之间接收和发送请求。其实现功能比较清晰,是一个相对较独立的模块,理解起来比较容易,所以首先介绍 它。 3.1 Ceph网络通信框架 一个分布式存储系统需要一个稳定的底层网络通信模块,用于各节点之间的互联互通。对于一个网络通信系统,要求如下: ·高性能。性能评价的两个指标:带宽和延迟。 ·稳定可靠。数据不丢包,在网络中断时,实现重连等异常处理。 网络通信模块的实现在源代码src/msg的目录下,其首先定义了一个网络通信的框架,三个子目录里分别对应:Simple、Async、XIO三种不同的实现方式。 Simple是比较简单,目前比较稳定的实现,系统默认的用于生产环境的方式。它最大的特点是:每一个网络链接,都会创建两个的线程,一个专门用于接收,一个专门用于发送。这种模式实现比较简 单,但是对于大规模的集群部署,大量的链接会产生大量的线程,会消耗CPU资源,影响性能。 Async模式使用了基于事件的I/O多路复用模式。这是目前网络通信中广泛采用的方式,但是在Ceph中,官方宣称这种方式还处于试验阶段,不够稳定,还不能用于生产环境。 XIO方式使用了开源的网络通信库accelio来实现。这种方式需要依赖第三方的库accelio稳定性,需要对accelio的使用方式以及代码实现都比较熟悉。目前也处于试验阶段。特别注意的是,前两种方式 只支持TCP/IP协议,XIO可以支持Infiniband网络。 在msg目录下定义了网络通信的抽象框架,它完成了通信接口和具体实现的分离。在其下分别有msg/simple子目录、msg/Async子目录、msg/xio子目录,分别对应三种不同的实现。 3.2 Simple实现 Simple在Ceph里实现比较早,目前也比较稳定,是在生产环境中使用的网络通信模块。如其名字所示,实现相对比较简单。下面具体分析一下,Simple如何实现Ceph网络通信框架的各个模块。 3.3 本章小结 本章介绍了Ceph的网络通信模块的框架,及目前生产环境中使用的Simple实现。它对每个链接都会有一个发送线程和接收线程用来处理发送和接收。实现的难点还在于网络链接出现错误时的各种错误 处理。 第4章 CRUSH数据分布算法 本章介绍Ceph的数据分布算法CRUSH,它是一个相对比较独立的模块,和其他模块的耦合性比较少,功能比较清晰,比较容量理解。在客户端和服务器都有CRUSH的计算,了解它可以更好地理解后面 的章节。 CRUSH算法解决了PG的副本如何分布在集群的OSD上的问题。本章首先介绍CRUSH算法的原理,并给出相应的示列,然后进一步分析其实现的一些核心代码。 4.1 数据分布算法的挑战 存储系统的数据分布算法要解决数据如何分布到集群中的各个节点和磁盘上,其面临如下的挑战: ·数据分布和负载的均衡。首先是数据分布均衡,使数据能均匀地分别在各个节点和磁盘上。其次是负载均衡,使数据访问(读写等操作)的负载在各个节点和磁盘上的负载均衡。 ·灵活应对集群伸缩。系统可以方便地增加或者删除存储设备(包括节点和设备失效的处理)。当增加或者删除存储设备后,能自动实现数据的均衡,并且迁移的数据尽可能地少。 ·支持大规模集群。为了支持大规模的存储集群,就要求数据分布算法维护的元数据相对较小,并且计算量不能太大。随着集群规模的增加,数据分布算法的开销比较小。 在分布式存储系统中,数据分布算法对于分布式存储系统至关重要。目前有两种基本实现方法,一种是基于集中式的元数据查询的方式,如HDFS的实现:文件的分布信息(layout信息)是通过访问集 中式元数据服务器获得;另一种是基于分布式算法以计算获得。例如一致性哈希算法(DHT)等。Ceph的数据分布算法CRUSH就属于后者。 4.2 CRUSH算法的原理 CRUSH算法的全称为:Controlled、Scalable、Decentralized Placement of Replicated Data,可控的、可扩展的、分布式的副本数据放置算法。 由第1章中介绍过的RADOS对象寻址过程可知,CRUSH算法解决PG如何映射到OSD列表中。其过程可以看成函数: CRHUSH(X)(OSDi, OSDj, OSDk) 输入参数: ·X为要计算的PG的pg_id。 ·Hierachical Cluster Map为Ceph集群的拓扑结构。 ·Placement Rules为选择策略。 输出一组可用的OSD列表。 下面将分别详细介绍Hierarchical Cluster Map的定义和组织方式。Placement rules定义了副本选择的规则。最后介绍Bucket随机选择算法的实现。 4.3 代码实现分析 在介绍了CRUSH算法的原理之后,下面就分析CRUSH算法实现的关键数据结构,并对算法具体实现函数进行分析。 4.4 对CRUSH算法的评价 通过以上分析,可以了解到CRUSH算法实质是一种可分层确定性伪随机选择算法,它是Ceph分布式文件系统的一个亮点和创新。 优点如下: ·输入元数据(cluster map、placement rule)较少,可以应对大规模集群。 ·可以应对集群的扩容和缩容。 ·采用以概率为基础的统计上的均衡,在大规模集群中可以实现数据均衡。 目前存在的缺点如下: ·在小规模集群中,会有一定的数据不均衡现象。 ·增加新设备时,导致旧设备之间也有数据的迁移。 4.5 本章小结 本章介绍了RADOS的数据分布算法CRUSH的原理。Hierarchical Cluster Map实质定义了存储集群的静态拓扑结构。Placement Rules开放了数据副本的选择规则,可以由用户自己定义和编辑。Bucket算法定 义了从bucket选择一个item的算法。通过本章可以了解CRUSH算法的具体实现,它实质是一个可分层的伪随机分布选择算法,是Ceph的一个创新,但它并不完美,需要许多改进。 第5章 Ceph客户端 本章介绍Ceph的客户端实现。客户端是系统对外提供的功能接口,上层应用通过它来访问Ceph存储系统。本章首先介绍Librados和Osdc两个模块,通过它们可直接访问RADOS对象存储系统。其次介绍 Cls扩展模块使用它们可方便地扩展现有的接口。最后介绍Librbd模块。由于Librados和Librbd的多数实现流程都比较类似,本章在介绍相关的数据结构后,只选取一些典型的操作流程介绍。 5.1 Librados Librados是RADOS对象存储系统访问的接口库,它提供了pool的创建、删除、对象的创建、删除、读写等基本操作接口。架构如图5-1所示。 在最上层是类RadosClient,它是Librados的核心管理类,处理整个RADOS系统层面以及pool层面的管理。类IoctxImpl实现单个pool层的对象读写等操作。OSDC模块实现了请求的封装和通过网络模 块发送请求的逻辑,其核心类Objecter完成对象的地址计算、消息的发送等工作。 图5-1 Librados架构图 5.2 OSDC OSDC是客户端比较底层的模块,其核心在于封装操作数据,计算对象的地址,发送请求和处理超时。 5.3 客户写操作分析 以下代码是通过Librados库的接口写入数据到对象中的典型例程,对象的其他操作过程都类似: rados_t cluster; rados_ioctx_t ioctx; rados_create( rados_conf_read_file(cluster, NULL); rados_connect(cluster); rados_ioctx_create(cluster, pool_name.c_str(), rados_write(ioctx, “foo“, buf, sizeof(buf), 0) 上述代码是C语言接口完成的,其流程如下: 1)首先调用rados_create函数创建一个RadosClient对象,输出为类型rados_t,它是一个void类型的指针,通过librados:RadosClient对象的强制转换产生。第二个参数id为一个标识符,一般传 入为NULL。 2)调用函数rados_conf_read来读取配置文件。第二个参数为配置文件的路径,如果是NULL,就搜索默认的配置文件。 3)调用rados_connect函数,它调用了RadosClient的connect函数,做相关的初始化工作。 4)调用函数rados_ioctx_create,它调用RadosClient的create_ioctx函数,创建pool相关的IoCtxImpl类,其输出为类型rados_ioctx_t,它也是void类型的指针,由IoCtxImpl对象转换而来。 5)调用函数rados_write函数,向该pool的名为“foo”的对象写入数据。其调用IoCtxImpl类的wrie操作。 5.4 Cls Cls是Ceph的一个模块扩展,它允许用户自定义对象的操作接口和实现方法,为用户提供了一种比较方便的接口扩展方式。目前rbd和lock等模块都使用了这种机制。 5.5 Librbd Librbd模块实现了RBD(rados block device)接口,其基于Librados实现了对RBD的基本操作。Librbd的架构如图5-3所示。 图5-3 Librbd的架构图 在最上层是Librbd层,模块cls_rbd是一个Cls扩展模块,实现了RBD的元数据相关的操作。RBD的数据访问直接通过该Librados来访问。在最底层是OSDC层完成数据的发送。 5.6 本章小结 本章大致介绍了客户端的各个模块的功能以及核心典型操作的处理流程。由于Librados和Librbd的代码比较庞大,承载了所有功能的接口,故一些功能本章没有介绍到或者介绍得比较简略,但是客户端 的代码有很大的类似性,通过了解典型流程,便不难理解其他代码。 第6章 Ceph的数据读写 本章介绍Ceph的服务端OSD(书中简称OSD模块或者OSD)的实现。其对应的源代码在src/osd目录下。OSD模块是Ceph服务进程的核心实现,它实现了服务端的核心功能。本章先介绍OSD模块静态类 图相关数据结构,再着重介绍服务端数据的写入和读取流程。 6.1 OSD模块静态类图 OSD模块的静态类图如图6-1所示。 OSD模块的核心类及其之间的静态类图说明如下: ·类OSD和类OSDService是核心类,处理一个osd节点层面的工作。在早期的版本中,OSD和OSDService是一个类。由于OSD的类承载了太多的功能,后面的版本中引入OSDService类,分担一部原OSD 类的功能。 ·类PG处理PG相关的状态维护以及实现PG层面的基本功能。其核心功能是用boost库的statechart状态机来实现的PG状态转换。 ·类ReplicatedPG继承了类PG,在其基础上实现了PG内的数据读写以及数据恢复相关的操作。 ·类PGBackend的主要功能是把数据以事务的形式同步到一个PG其他从OSD节点上。 ·PGBackend的内部类PGTransaction就是同步的事务接口,其两个类型的实现分别对应RPGTransaction和ECTransaction两个子类。 ·PGBackend两个子类ReplicatedBackend和ECBackend分别对应PG的两种类型的实现。 ·类SnapMapper额外保存对象和对象的快照信息,在对象的属性里保存了相关的快照信息。这里保存的快照信息为冗余信息,用于数据效验。 图6-1 OSD模块的静态类图 6.2 相关数据结构 下面将介绍OSD模块相关的一些核心的数据结构。从最高的逻辑层次为pool的概念,然后是PG的概念。其次是OSDMap记录了集群的所有的配置信息。数据结构OSDOp是一个操作上下文的封装。结 构object_info_t保存了一个对象的元数据信息和访问信息。对象ObjectState是在object_info_t基础上添加了一些内存的状态信息。SnapSetContext和ObjectContext分别保存了快照和对象的上下文相关 的信息。Session保存了一个端到端的链接相关的上下文信息。 6.3 读写操作的序列图 写操作序列图如图6-2所示。 写操作分为三个阶段: ·阶段一 从函数ms_fast_dispatch到函数op_wq.queue函数为止,其处理过程都

    注意事项

    本文(Ceph源码分析.html.pdf)为本站会员(紫竹语嫣)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开