ceph源码分析之读写操作流程(2)
Ceph中的容量计算与管理(结合cephdf命令讲解)

Ceph 中的容量计算与管理(结合cephdf 命令讲解)展开全文在部署完Ceph 集群之后,一般地我们可以通过Ceph df 这个命令来查看集群的容量状态,但是Ceph 是如何计算和管理的呢?相信大家都比较好奇。
因为用过 ceph df 这个命令的人都会有这个疑问,它的输出到底是怎么计算的呢?为什么所有pool 的可用空间有时候等于GLOBAL 中的可用空间,有时候不等呢? 带着这些疑问我们可以通过分析ceph df 的实现,来看看Ceph 是如何计算容量和管理容量的。
一般情况下ceph df 的输出如下所示:ceph-df1 2 3 4 5 6 7 8 [root@study-1 ~]# ceph dfGLOBAL:SIZE AVAIL RAW USED %RAW USED 196G 99350M 91706M 45.55POOLS:NAME ID USED %USED MAX AVAIL OBJECTSrbd 1 20480k 0.02 49675M 11x 2 522 0 49675M 11从上面的输出可以看到,ceph 对容量的计算其实是分为两个维度的。
一个是GLOBAL 维度,一个是POOLS 的维度。
GLOBAL 维度中有SIZE ,AVAIL ,RAW USED ,%RAW USED 。
POOLS 维度中有 USED ,%USED ,MAX AVAIL ,OBJECTS 。
我们这里先把注意力放在RAW USED ,和AVAIL 上。
这个两个分析清楚之后,其它的也就迎刃而解了。
这里我们粗略算一下GLOBAL 中的RAW USED 为91706M ,明显大于下面pool 中USED 20480k*3 + 522bytes*3啊。
而且各个pool 的MAX AVAIL 相加并不等于GLOBAL 中的AVAIL 。
我们需要深入代码分析一下为什么。
分析Ceph 命令基本上都是首先到Montior 这里,如何Monitor 能处理请求,就直接处理,不能就转发。
java操作ceph之rbd基本操作

java操作ceph之rbd基本操作⼀、安装librados和librbdCeph存储集群提供了基本的存储服务,允许Ceph在⼀个统⼀的系统中唯⼀地传送对象,块和⽂件存储。
但是,不限于使⽤RESTful,块或POSIX接⼝。
基于RADOS,Librados API使您能够创建⾃⼰的Ceph存储群集接⼝。
Librados API使您能够与Ceph存储集群中的两种守护程序进⾏交互:1)Ceph监视器,其维护集群映射的主副本。
2)Ceph OSD守护程序(OSD),它将数据作为对象存储在存储节点上。
要安装librados-dev和librbd-dev,因为java的Rados类需要⽤到librados-dev,⽽Rbd类需要⽤到librbd-dev,需要执⾏以下步骤:1)安装librados和librbd。
对于Debian / Ubuntu,执⾏:apt-get install librados-devapt-get install librbd-dev对于 CentOS/RHEL,执⾏:yum install librados2-develyum install librbd1-devel为开发⼈员安装库后,可以在/usr/include/rados下找到C / C ++所需的头⽂件也可以下载下⾯的4个rmp包:然后执⾏:yum install librados2-0.94.5-1.el7.x86_64.rpm librados2-devel-0.94.5-1.el7.x86_64.rpm -yyum install librbd1-0.94.5-1.el7.x86_64.rpm librbd1-devel-0.94.5-1.el7.x86_64.rpm -y2)克隆rados-java⼯程:git clone https:///ceph/rados-java.git3)构建rados-java⼯程:cd rados-java-mastermvn install -Dmaven.test.skip=trueJAR⽂件位于rados-java-master/target下4)新建⼀个maven⼯程cephDemo,⽤来调⽤ceph⼯程⽬录如下所⽰:下⾯引⽤的rados-0.4.0-SNAPSHOT.jar是由上⾯的mvn install后⽣成的jar包,实情情况版本可能有变pom.xml配置如下:<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd" <modelVersion>4.0.0</modelVersion><groupId>com.ceph.test</groupId><artifactId>cephDemo</artifactId><version>0.0.1-SNAPSHOT</version><name>cephDemo</name><dependencies><dependency><groupId>com.ceph</groupId><artifactId>rados</artifactId><version>0.4.0-SNAPSHOT</version></dependency></dependencies></project>⼆、应⽤程序调⽤ceph原理下图提供了初始连接的⾼级流程。
Ceph源码解析:CRUSH算法

Ceph源码解析:CRUSH算法1、简介随着⼤规模分布式存储系统(PB级的数据和成百上千台存储设备)的出现。
这些系统必须平衡的分布数据和负载(提⾼资源利⽤率),最⼤化系统的性能,并要处理系统的扩展和硬件失效。
ceph设计了CRUSH(⼀个可扩展的伪随机数据分布算法),⽤在分布式对象存储系统上,可以有效映射数据对象到存储设备上(不需要中⼼设备)。
因为⼤型系统的结构式动态变化的,CRUSH能够处理存储设备的添加和移除,并最⼩化由于存储设备的的添加和移动⽽导致的数据迁移。
为了保证负载均衡,保证新旧数据混合在⼀起。
但是简单HASH分布不能有效处理设备数量的变化,导致⼤量数据迁移。
ceph开发了CRUSH(Controoled Replication Under Scalable Hashing),⼀种伪随机数据分布算法,它能够在层级结构的存储集群中有效的分布对象的副本。
CRUSH实现了⼀种伪随机(确定性)的函数,它的参数是object id或object group id,并返回⼀组存储设备(⽤于保存object副本OSD)。
CRUSH需要cluster map(描述存储集群的层级结构)、和副本分布策略(rule)。
CRUSH有两个关键优点:任何组件都可以独⽴计算出每个object所在的位置(去中⼼化)。
只需要很少的元数据(cluster map),只要当删除添加设备时,这些元数据才需要改变。
CRUSH的⽬的是利⽤可⽤资源优化分配数据,当存储设备添加或删除时⾼效地重组数据,以及灵活地约束对象副本放置,当数据同步或者相关硬件故障的时候最⼤化保证数据安全。
⽀持各种各样的数据安全机制,包括多⽅复制(镜像),RAID奇偶校验⽅案或者其他形式的校验码,以及混合⽅法(⽐如RAID-10)。
这些特性使得CRUSH适合管理对象分布⾮常⼤的(PB级别)、要求可伸缩性,性能和可靠性⾮常⾼的存储系统。
简⽽⾔之就是PG到OSD的映射过程。
详细解读NFS 文件系统源代码

详细解读NFS 文件系统源代码NFS 文件系统概述NFS(Network File System,网络文件系统)是一种基于网络的文件系统。
它可以将远端服务器文件系统的目录挂载到本地文件系统的目录上,允许用户或者应用程序像访问本地文件系统的目录结构一样,访问远端服务器文件系统的目录结构,而无需理会远端服务器文件系统和本地文件系统的具体类型,非常方便地实现了目录和文件在不同机器上进行共享。
虽然NFS 不是唯一实现这个功能的文件系统,但它无疑是最成功一个。
NFS 的第一个版本是SUN Microsystems 在20 世纪80 年代开发出来的,至今为止,NFS 经历了NFS,NFSv2,NFSv3 和NFSv4 共四个版本。
现在,NFS 最新的版本是4.1,也被称为pNFS(parallel NFS,并行网络文件系统)。
前四个版本的NFS,作为一个文件系统,它几乎具备了一个传统桌面文件系统最基本的结构特征和访问特征,不同之处在于它的数据存储于远端服务器上,而不是本地设备上,因此不存在磁盘布局的处理。
NFS 需要将本地操作转换为网络操作,并在远端服务器上实现,最后返回操作的结果。
因此,NFS 更像是远端服务器文件系统在本地的一个文件系统代理,用户或者应用程序通过访问文件系统代理来访问真实的文件系统。
众所周知的是,NFS 的客户端在访问远端服务器文件系统时,既需要通过服务器获得文件的属性信息,还需要通过服务器获得文件的数据信息,这使得NFS 天然地具备将文件的属性信息和数据信息分离在不同服务器上进行访问的特性,于是最后一个版本NFS4.1/pNFS,将Lustre/CephFS/GFS 等集群文件系统的设计思想引入到自身中,成为一个具有里程碑意义的NFS 版本。
它使得NFS 的数据吞吐的速度和规模都得到了极大提高,为NFS 的应用带了更为广阔的空间。
NFS 之所以备受瞩目,除了它在文件共享领域上的优异表现外,还有一个关键原因在于它在NAS 存储系统上应用。
ceph接口使用方法

ceph接口使用方法Ceph接口使用方法Ceph是一个开源的分布式存储系统,拥有强大的可扩展性和高可靠性。
它通过将数据分布在多个节点上,实现了数据冗余和负载均衡的功能。
Ceph提供了一系列的接口,让开发者可以轻松地使用其功能。
本文将介绍Ceph接口的使用方法,包括安装和配置Ceph、使用Ceph 接口进行数据操作等。
通过本文的指导,读者可以快速上手并深入了解Ceph接口的使用。
第一步:安装Ceph在开始使用Ceph接口之前,首先需要在集群中安装和配置Ceph。
Ceph 可以在Linux系统上运行,支持多种发行版。
以下是在Ubuntu上安装Ceph的步骤:1. 更新系统软件包:使用以下命令更新系统软件包以获取最新的软件包列表和安全修复程序。
sudo apt-get updatesudo apt-get upgrade2. 安装Ceph软件包:使用以下命令安装Ceph软件包。
sudo apt-get install ceph ceph-deploy3. 配置Ceph集群:使用Ceph提供的命令行工具ceph-deploy来配置Ceph集群。
首先需要创建一个新的目录作为Ceph集群的工作目录。
mkdir my-clustercd my-cluster然后,在此目录下,运行以下命令来初始化Ceph集群。
ceph-deploy new <MON节点>这将在当前目录下创建一个名为ceph.conf的配置文件,其中包含了集群的基本配置信息。
接下来,使用以下命令将Ceph软件包安装到集群的所有节点。
ceph-deploy install <所有节点>最后,使用以下命令来为集群添加MON节点。
ceph-deploy mon create-initial第二步:配置Ceph存储池一旦Ceph集群安装和配置完成,下一步是创建一个或多个存储池,以供存储数据。
存储池是Ceph中最基本的单元,用于管理数据的存储和分发。
【Ceph】Ceph进阶系列(一):Ceph日志和调试[new]
![【Ceph】Ceph进阶系列(一):Ceph日志和调试[new]](https://img.taocdn.com/s3/m/b3046e68178884868762caaedd3383c4bb4cb47e.png)
【Ceph】Ceph进阶系列(⼀):Ceph⽇志和调试[new]⽬录即看即⽤1 运⾏时查看配置运⾏时执⾏下列命令,⽤ osd 、 mon 或 mds 替代 {daemon-type}:ceph daemon {daemon-name} config show | less例如:ceph daemon osd.0 config show | less激活 Ceph 的调试输出(dout() )ceph tell 命令把参数注⼊运⾏时配置:ceph tell {daemon-type}.{daemon id or *} injectargs --{name} {value} [--{name} {value}]⽤ osd 、 mon 或 mds 替代 {daemon-type} 。
* 同类型的所有守护进程,id:指定具体守护进程。
例如:ceph tell osd.0 injectargs --debug-osd 0/5ceph tell 命令会通过 monitor 起作⽤。
如果你不能绑定 monitor,仍可以登录你要改的那台主机然后⽤ ceph daemon 来更改。
例如: sudo ceph daemon osd.0 config set debug_osd 0/52 启动时激活 Ceph 的调试输出(dout() )把选项加⼊配置⽂件,[global]段:各进程共有,[mon]、[osd]、[mds] :某类进程的配置。
例如:[global]debug ms = 1/5[mon]debug mon = 20debug paxos = 1/5debug auth = 2[osd]debug osd = 1/5debug filestore = 1/5debug journal = 1debug monc = 5/20[mds]debug mds = 1debug mds balancer = 1debug mds log = 1debug mds migrator = 13 加速⽇志更迭logrotate是linux下负责检查⽇志和切割轮转的服务,它的配置⽂件在 /etc/logrotate.d/⽬录下,/etc/logrotate.d/ceph是ceph添加的配置,例如默认配置⼤致如此:rotate 7weeklycompresssharedscripts增加⼀个 size 选项,表⽰当⽇志的size达到500M就执⾏切割和轮转( rotate 7只保留最近7个⽇志⽂件)rotate 7weeklysize 500Mcompresssharedscripts然后,打开 crontab 编辑器。
ceph磁盘挂载详解rbd cephfs

8:验证挂载信息:
config file /etc/modprobe.conf, all config files belong into /etc/modprobe.d/.
df -h
Filesystem Size Used Avail Use% Mounted on
12:查看创建的池
ceph osd lspools
13:从池中取出一个块设备,请执行以下命令,请更换大括号内相关的镜像的名字,池的名称替换{池名称}的名称及替换大括号内{镜像}名称:
rbd rm {image-name} -p {pool-name} 示例:
rbd rm rbdpoolimages -p rbdpool
##########################cephFS挂载####################################
创建cephfs文件系统
对于一个刚创建的MDS服务,虽然服务是运行的,但是它的状态直到创建 pools 以及文件系统的时候才会变为Active.
3:验证数据生成
[root@web-3-136 ~]# ceph mds stat
e10: 1/1/1 up {0=dn-5-228=up:active}, 2 up:standby
##########################cephfs客户端挂载###############################
4:验证挂载结果:
df -Th
Filesystem Type Size Used Avail Use% Mounted on
172.17.5.225:6789:/ ceph 30T 648M 30T 1% /cephfs
Ceph入门篇

Ceph⼊门篇Ceph 初探1. Ceph 简介Ceph是⼀个可靠地、⾃动重均衡、⾃动恢复的分布式存储系统,根据场景划分可以将Ceph分为三⼤块,分别是对象存储、块设备存储和⽂件系统服务。
在虚拟化领域⾥,⽐较常⽤到的是Ceph的块设备存储,⽐如在 OpenStack 项⽬⾥,Ceph 的块设备存储可以对接 OpenStack 的 Cinder后端存储、Glance的镜像存储和虚拟机的数据存储,⽐较直观的是Ceph集群可以提供⼀个raw格式的块存储来作为虚拟机实例的硬盘。
Ceph相⽐其它存储的优势点在于它不单单是存储,同时还充分利⽤了存储节点上的计算能⼒,在存储每⼀个数据时,都会通过计算得出该数据存储的位置,尽量将数据分布均衡,同时由于Ceph的良好设计,采⽤了CRUSH算法、HASH环等⽅法,使得它不存在传统的单点故障的问题,且随着规模的扩⼤性能并不会受到影响。
2. Ceph 核⼼组件及功能介绍Ceph的核⼼组件包括Ceph OSD、Ceph Monitor、Ceph Manager和Ceph MDS。
Ceph OSDOSD的英⽂全称是Object Storage Device,它的主要功能是存储数据、复制数据、平衡数据、恢复数据等,并通过检查其他Ceph OSD守护程序的⼼跳来向 Ceph 监视器和管理器提供⼀些监视信息。
通常⾄少需要3个Ceph OSD才能实现冗余和⾼可⽤性。
⼀般情况下⼀块硬盘对应⼀个OSD,由OSD来对硬盘存储进⾏管理,当然⼀个分区也可以成为⼀个OSD。
Ceph OSD的架构实现由物理磁盘驱动器、Linux⽂件系统和Ceph OSD服务组成,对于Ceph OSD Deamon⽽⾔,Linux⽂件系统显性的⽀持了其拓展性,⼀般Linux⽂件系统有好⼏种,⽐如有BTRFS、XFS、Ext4等,BTRFS虽然有很多优点特性,但现在还没达到⽣产环境所需的稳定性,⼀般⽐较推荐使⽤XFS。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ceph源码分析之读写操作流程(2)上一篇介绍了ceph存储在上两层的消息逻辑,这一篇主要介绍一下读写操作在底两层的流程。
下图是上一篇消息流程的一个总结。
上在ceph中,读写操作由于分布式存储的原因,故走了不同流程。
对于读操作而言:1.客户端直接计算出存储数据所属于的主osd,直接给主osd 上发送消息。
2.主osd收到消息后,可以调用Filestore直接读取处在底层文件系统中的主pg里面的内容然后返回给客户端。
具体调用函数在ReplicatedPG::do_osd_ops中实现。
读操作代码流程如图:如我们之前说的,当确定读操作为主osd的消息时(CEPH_MSG_OSD_OP类型),会调用到ReplicatePG::do_osd_op函数,该函数对类型做进一步判断,当发现为读类型(CEPH_OSD_OP_READ)时,会调用FileStore中的函数对磁盘上数据进行读。
[cpp] view plain copy int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops) { ……switch (op.op) { …… caseCEPH_OSD_OP_READ: ++ctx->num_read; { // read into a buffer bufferlistbl; int r = osd->store->read(coll, soid, op.extent.offset, op.extent.length, bl); // 调用FileStore::read从底层文件系统读取……} caseCEPH_OSD_OP_WRITE:++ctx->num_write; { ……//写操作只是做准备工作,并不实际的写} ……} } FileStore::read 函数是底层具体的实现,会通过调用系统函数如::open,::pread,::close等函数来完成具体的操作。
[cpp] view plain copy int FileStore::read( coll_t cid, const ghobject_t& oid, uint64_t offset, size_t len, bufferlist& bl, bool allow_eio) { ……int r = lfn_open(cid, oid, false, &fd); ……got = safe_pread(**fd, bptr.c_str(), len, offset);//FileStore::safe_pread中调用了::pread ……lfn_close(fd); ……} 而对于写操作而言,由于要保证数据写入的同步性就会复杂很多:1.首先客户端会将数据发送给主osd,2.主osd同样要先进行写操作预处理,完成后它要发送写消息给其他的从osd,让他们对副本pg进行更改,3.从osd通过FileJournal完成写操作到Journal中后发送消息告诉主osd说完成,进入54.当主osd收到所有的从osd完成写操作的消息后,会通过FileJournal完成自身的写操作到Journal中。
完成后会通知客户端,已经完成了写操作。
5.主osd,从osd的线程开始工作调用Filestore将Journal中的数据写入到底层文件系统中。
在介绍写操作的流程前,需要先介绍一下ceph中的callback函数。
Context类定义在src/include文件中,该类是一个回调函数类的抽象类,继承它的类只要在子类实现它的finish函数,在finish函数调用自己需要回调的函数,就可以完成回调。
[cpp] view plain copy class Context { Context(const Context& other); const Context&operator=(const Context& other); protected:virtual void finish(int r) = 0; public: Context() {} virtual ~Context() {} // we want a virtual destructor!!! virtual void complete(int r) { finish(r); delete this; } }; Finisher类是在src/common中定义的一个专门查看操作是否结束的一个类。
在这个类里面拥有一个线程finisher_thread和一个类型为Context指针的队列finisher_queue。
当一个操作线程完成自己的操作后,会将Context类型对象送入队列。
此时finisher_thread线程循环监视着自己的finisher_queue队列,当发现了有新进入的Context时,会调用这个Context::complete函数,这个函数则会调用到Context子类自己实现的finish函数。
来处理操作完成后的后续工作。
[cpp] view plain copy class Finisher { CephContext*cct; …… vector<Context*>finisher_queue; …… void*finisher_thread_entry(); struct FinisherThread : public Thread { Finisher *fin;FinisherThread(Finisher *f) : fin(f) {} void* entry() { return (void*)fin->finisher_thread_entry(); } } finisher_thread; …… } void*Finisher::finisher_thread_entry() { ……while(!finisher_stop){ while(!finisher_queue.empty( )){ ……vector<Context*> lsls.swap(finisher_queue); for(vector<Context*>::iterator p = ls.begin();p != ls.end(); ++p) { if (*p) { //这里面调用Context子类实现的finish函数(*p)->complete(0); } } } } } 在写操作中涉及了多个线程和消息队列的协同工作,需要注意的是一个类拥有一个Finisher 成员时,以为着它同时获得了一个队列和一个执行线程。
OSD中处理读写操作是线程池和消息队列(有很多,其他暂时不讨论):[cpp] view plain copy ThreadPool op_tp;ThreadPool::WorkQueueVal<pair<PGRef,OpRequestRef& gt;, PGRef> &op_wq;FileJournal中拥有的线程和消息队列:[cpp] view plain copy Write write_thread;deque<write_item> writeq;其父类Journal中拥有线程和消息队列(引用自之前说的JournalingObjectStore类中):[cpp] view plain copy Finisher finisher_thread; FileStore中拥有的线程和消息队列:[cpp] view plain copy ThreadPool op_tp; OpWQop_wq;//Filestore中实现,继承自ThreadPool::WorkQueue<OpSequencer> Finisher ondisk_finisher; Finisher op_finisher; 前一章说过在前两层,OSD根据不同的消息类型,选择了主OSD处理和从OSD的处理,以下介绍的写流程,就是在收到具体写操作以后,本地OSD开始的工作。
写的逻辑流程图如图:从图中我们可以看到写操作分为以下几步:1.OSD::op_tp线程从OSD::op_wq中拿出来操作如本文开始的图上描述,具体代码流是ReplicatePG::apply_repop中创建回调类C_OSD_OpCommit和C_OSD_OpApplied FileStore::queue_transactions中创建了回调类C_JournaledAhead2.FileJournal::write_thread线程从FileJournal::writeq中拿出来操作,主要就是写数据到具体的journal中,具体代码流:3.Journal::Finisher.finisher_thread线程从Journal::Finisher.finish_queue中拿出来操作,通过调用C_JournalAhead留下的回调函数FileStore:_journaled_ahead,该线程开始工作两件事:首先入底层FileStore::op_wq通知开始写,再入FileStore::ondisk_finisher.finisher_queue通知可以返回。
具体代码流:4.FileStore::ondisk_finisher.finisher_thread 线程从FileStore::ondisk_finisher.finisher_queue中拿出来操作,通过调用C_OSD_OpCommit留下来的回调函数ReplicatePG::op_commit,通知客户端写操作成功5.FileStore::op_tp线程池从FileStore::op_wq中拿出操作(此处的OP_WQ继承了父类ThreadPool::WorkQueue重写了_process和_process_finish等函数,所以不同于OSD::op_wq,它有自己的工作流程),首先调用FileStore::_do_op,完成后调用FileStore::_finish_op。
6.FileStore::op_finisher.finisher_thread线程从FileStore::op_finisher.finisher_queue中拿出来操作,通过调用C_OSD_OpApplied留下来的回调函数ReplicatePG::op_applied,通知数据可读。