Ceph作为一个高可用和强一致性的软件定义存储实现,去使用它非常重要的就是了解其内部的IO路径和存储实现。这篇文章主要介绍在IO路径中最底层的ObjectStore的实现之一FileStore。

ObjectStore

ObjectStore是Ceph OSD中最重要的概念之一,它封装了所有对底层存储的IO操作。从上图中可以看到所有IO请求在Clieng端发出,在Message层统一解析后会被OSD层分发到各个PG,每个PG都拥有一个队列,一个线程池会对每个队列进行处理。

当一个在PG队列里的IO被提出后,该IO请求会被根据类型和相关附带参数进行处理。如果是读请求会通过ObjectStore提供的API获得相应的内容,如果是写请求也会利用ObjectStore提供的事务API将所有写操作组合成一个原子事务提交给ObjectStore。ObjectStore通过接口对上层提供不同的隔离级别,目前PG层只采用了Serializable级别,保证读写的顺序性。

ObjectStore主要接口分为三部分,第一部分是Object的读写操作,类似于POSIX的部分接口,第二部分是Object的属性(xattr)读写操作,这类操作的特征是kv对并且与某一个Object关联。第三部分是关联Object的kv操作(在Ceph中称为omap),这个其实与第二部分非常类似,但是在实现上可能会有所变化。

目前ObjectStore的主要实现是FileStore,也就是利用文件系统的POSIX接口实现ObjectStore API。每个Object在FileStore层会被看成是一个文件,Object的属性(xattr)会利用文件的xattr属性存取,因为有些文件系统(如Ext4)对xattr的长度有限制,因此超出长度的Metadata会被存储在DBObjectMap里。而Object的omap则直接利用DBObjectMap实现。因此,可以看出xattr和omap操作是互通的,在用户角度来说,前者可以看作是受限的长度,后者更宽泛(API没有对这些做出硬性要求)。

FileJournal

为了缩小写事务的处理时间,提高写事务的处理能力并且实现事务的原子性,FileStore引入了FileJournal,所有写事务在被FileJournal处理以后都会立即返回(上图中的第二步)。FileJournal类似于数据库的writeahead日志,使用O_DIRECT和O_DSYNC每次同步写入到journal文件,完成后该事务会被塞到FileStore的op queue。事务通常有若干个写操作组成,当在中间过程进程crash时,journal会OSD recover提供了完备的输入。FileStore会存在多个thread从op queue里获取op,然后真正apply到文件系统上对应的Object(Buffer IO)。当FileStore将事务落到disk上之后,后续的该Object的读请求才会继续(上图中的第五步)。当FileStore完成一个op后,对应的Journal可以丢弃这部分日志。

实际上并不是所有的文件系统都按照这个顺序,一般来说如Ceph推荐的Ext4和XFS文件系统会先写入Journal,然后再写入Filesystem,而COW(Copy on Write)文件系统如Btrfs和ZFS会同时写入Journal和FileSystem。

DBObjectMap

DBObjectMap是FileStore的一部分,利用KeyValue数据库实现了ObjectStore的第三部分API,DBObjectMap主要复杂在其实现了clone操作的no-copy。因为ObjectStore提供了clone API,提供对一个Object的完全clone(包括Object的属性和omap)。DBObjectMap对每一个Object有一个Header,每个Object联系的omap(kv pairs)对会与该Header联系,当clone时,会产生两个新的Header,原来的Header作为这两个新Header的parent,这时候无论是原来的Object还是cloned Object在查询或者写操作时都会查询parent的情况,并且实现copy-on-write。那么Header如何与omap(kv pairs)联系呢,首先每个Header有一个唯一的seq,然后所有属于该Header的omap的key里面都会包含该seq,因此,利用KeyValueDB的提供的有序prefix检索来实现对omap的遍历。

上面提到FileStore会将每个Object作为一个文件,那么Object的一些属性会与Object Name一起作为文件名,Object 所属的PG会作为文件目录,当一个PG内所包含的文件超过一定程度时(在目录内文件太多会造成文件系统的lookup性能损耗),PG会被分裂成两个PG。

 

解析CEPH SNAPSHOT

Posted on 2013年12月27日 by kernal

经常有开发者在邮件列表中会问到Ceph Snapshot的实现方式,受限于目前有限的实现文档和复杂的代码结构和代码量,弄清楚Ceph Snapshot并不是一件容易的事。正好最近在重构Ceph存储引擎层的DBObjectMap,涉及到处理Snapshot间clone的问题,重新梳理了一次在Ceph IO路径中占了非常大比重的snapshot相关代码流程,在这里并不会重点展现里面的代码或者数据结构,而是从高层设计角度展现Snapshot的实现。

在阅读下文前务必先了解Ceph的基本情况和使用场景。什么是ceph怎样使用ceph

Ceph Snapshot使用场景

多数人尝试Ceph的Snapshot往往从Ceph的RBD库入手,也就是所谓的块存储。利用librbd通过简单的命令可以快速创建卷和Snapshot。

rbd create image-name –size 1024 -p pool

rbd snap create pool/image-name –snap snap-name

第一条命令创建了一个名为”image-name”的卷,在这个过程中librbd库只是创建了一个metadata而没有实际向Ceph申请空间。关于librbd如何利用Rados实现块存储和管理更多的细节会在以后的文章中讲到,这里先留个坑。

第二条命令对”image-name”卷创建了一个名为”snap-name”的Snapshot,创建以后,对”image-name”卷的任意写操作之后都可以在任意时间回滚到创建”snap-name”的Snapshot时的数据。如下面这条命令

rbd snap rollback pool/image-name –snap snap-name

在用户实际尝试过程中,会发现Ceph对于卷的操作和管理非常轻量,任意时刻,任意卷大小,任意集群大小的卷创建都是相同的操作量级,在其背后实质上也是完全相同的操作。开发者会对如何实现Snapshot更敢兴趣,因为Snapshot的实现方式决定了如何有效的使用Snapshot。

Ceph Snapshot实现

在阐述之前,首先要了解Ceph有Pool的概念,也就是上面命令上涉及到的-p pool。一个Ceph Cluster可以创建多个Pool,每个Pool是逻辑上的隔离单位,不同的Pool可以有完全不同的数据处理方式。如Replication Size(副本数),Placement Groups(PG),CRUSH Rules,Snapshots,Ownership都是利用Pool进行隔离的。

因此,对Ceph的任意操作都需要先指定Pool才能进行,上面的image操作都是在一个名为”pool”的Pool上进行,名为”image-name”的Image也是存储在”pool”中。

除了Pool概念外,Ceph实质上有两种Snapshot模式,并且两种Snapshot是不能同时应用到同一个Pool中。

  1. Pool Snapshot: 对整个Pool打一个Snapshot,该Pool中所有的对象都会受影响
  2. Self Managed Snapshot: 用户管理的Snapshot,简单的理解就是这个Pool受影响的对象是受用户控制的。这里的用户往往是应用如librbd。

我们在前面利用rbd命令的操作实质上是使用第二种模式,因此我们先首先介绍第二种模式的实现。

在前面提到,Snapshot也是利用Pool隔离的,两种Snapshot mode的实现是基本相似的,如何使用是造成两种模式分离的重要原因。每个Pool都有一个snap_seq字段,该字段可以认为是整个Pool的Global Version。所有存储在Ceph的Object也都带有snap_seq,而每个Object会有一个Head版本的,也可能会存在一组Snapshot objects,不管是Head版本还是snapshot object都会带有snap_seq,那么接下来我们看librbd是如何利用该字段创建Snapshot的。

  1. 用户申请为”pool”中的”image-name”创建一个名为”snap-name”的Snapshot
  2. librbd向Ceph Monitor申请得到一个”pool”的snap sequence,Ceph Monitor会递增该Pool的snap_seq,然后返回该值给librbd。
  3. librbd将新的snap_seq替换原来image的snap_seq中,并且将原来的snap_seq设置为用户创建的名为”snap-name”的Snapshot的snap_seq

从上面的操作中,对于版本控制实现熟悉的同学们可能就大致猜测出Ceph对于Snapshot的实现了。每个Snapshot都掌握者一个snap_seq,Image可以看成一个Head Version的Snapshot,每次IO操作对会带上snap_seq发送给Ceph OSD,Ceph OSD会查询该IO操作涉及的object的snap_seq情况。如”object-1″是”image-name”中的一个数据对象,那么初始的snap_seq就”image-name”的snap_seq,当创建一个Snapshot以后,再次对”object-1″进行写操作时会带上新的snap_seq,Ceph接到请求后会先检查”object-1″的Head Version,会发现该写操作所带有的snap_seq大于”object-1″的snap_seq,那么就会对原来的”object-1″克隆一个新的Object Head Version,原来的”object-1″会作为Snapshot,新的Object Head会带上新的snap_seq,也就是librbd之前申请到的。

Ceph的实现当然比上面提到的要复杂很多,要考虑更多的异常情况还有管理Object Snaps上。

上述提到的是第二种Snapshot Mode,那么第一种模式实际上更简单。既然第二种方式是应用(librbd)自己申请snap_seq,然后进行管理,那么第一种是的场景可以是命令如”rados mksnap snap-name -p pool”进行全局pool的Snapshot,应用是不需要知道snap_seq的。这条命令会递增”pool”的snap_seq,然后接下来所有”pool”下的objects对会受影响,因为所有的接下来的IO操作都会自动继承”pool”的snap_seq,对object进行clone。在CephFS里用到这个模式管理全局的Snapshot。

所以,更简单的讲,这两者mode的区别就在于应用进行IO请求时是否附带snap_seq。

Object Snapshot的存储管理

上面提到的都是如何利用snap_seq向底层存储查找相应的对象然后返回,那么底层的存储引擎是如何管理一个Object的不同版本的呢。

首先,任一个Object都是通过ObjectStore接口进行访问,目前Ceph Master分支支持MemStore和FileStore两种,FileStore是默认的存储接口实现。以后的文章也会介绍具体的FileStore实现。

在Ceph中,每一个Object都有三种类型的存储接口,分别是最主要的Object存储,xattr存储和omap存储。Object存储就是用户实际数据的存放,xattr主要用来给CephFS提供XATTR数据存放,omap存储可以理解成一个k/v存储并且与某一个object相关联。而一个Object的元数据(pool,PG,name等等)都有一个object_info_t的结构进行管理,有一个SnapSetContext结构管理Snapshots,两者都作为一个object的k/v存储持久化。默认的FileStore是利用LevelDB作为键值存储,然后通过DBObjectMap类对LevelDB进行映射管理。

在Snapshot的实现上,最重要的其实就是Clone操作,那么在FileStore层面,Object数据存储是实际上就是一个文件,Object间克隆依赖OSD数据目录的文件系统,如Ext4或者XFS会直接完全拷贝数据,使用Btrfs会利用ioctl的BTRFS_IOC_CLONE_RANGE命令,kv数据克隆通过一个巧妙的KeyMapping实现COW策略(略微复杂,后面文章解读),而xattr则完全copy实现(xattr在Ceph中较少用到)。

本文出自 “西伯利亚·狼” 博客,请务必保留此出处http://kernal.blog.51cto.com/8136890/1540535

解析CEPH: 存储引擎实现之一 filestore的更多相关文章

  1. ceph存储引擎bluestore解析

    原文链接:http://www.sysnote.org/2016/08/19/ceph-bluestore/ ceph后端支持多种存储引擎,以插件式的方式来进行管理使用,目前支持filestore,k ...

  2. 解析Ceph: Snapshot

    经常有开发者在邮件列表中会问到Ceph Snapshot的实现方式,受限于目前有限的实现文档和复杂的代码结构和代码量,弄清楚Ceph Snapshot并不是一件容易的事.正好最近在重构Ceph存储引擎 ...

  3. Ceph Newstore存储引擎介绍

    在Ceph被越来越多地应用于各项存储业务过程中,其性能及调优策略也成为用户密切关注讨论的话题,影响性能表现关键因素之一即OSD存储引擎实现:Ceph基础组件RADOS是强一致.对象存储系统,其OSD底 ...

  4. [ ceph ] BlueStore 存储引擎介绍

    为什么需要 BlueStore 首先,Ceph原本的FileStore需要兼容Linux下的各种文件系统,如EXT4.BtrFS.XFS.理论上每种文件系统都实现了POSIX协议,但事实上,每个文件系 ...

  5. MySQL存储引擎之Spider内核深度解析

      作者介绍 朱阅岸,中国人民大学博士,现供职于腾讯云数据库团队.研究方向主要为数据库系统理论与实现.新硬件平台下的数据库系统以及TP+AP型混合系统. Spider是为MySQL/MariaDB开发 ...

  6. MySQL InnoDB存储引擎undo redo解析

    本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...

  7. 第二课——解析mysqldump命令和mysqlbinlog命令+innodb和Myisam存储引擎简介

    环境说明 mysql版本:Percona-Server-5.6.30 IP:10.7.15.167 端口:3306 安装目录:/httx/run/mysql 数据目录:/httx/run/mysql/ ...

  8. 图文实例解析,InnoDB 存储引擎中行锁的三种算法

    前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁.具体来说,InnoDB 采用的是两阶段锁定协议(tw ...

  9. 解析 Ceph: FileJournal 的作用

      很多的用户在提到 Ceph 性能的时候都会提到“写放大”这点,实际上就是 FileJournal 在起作用.只要使用默认的 FileStore,所有数据包括 metadata 都会在 FileJo ...

随机推荐

  1. PAT 1014 Waiting in Line (模拟)

    1014. Waiting in Line (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Suppo ...

  2. ChannelOption用到的socket的标准参数

    ChannelOption.SO_BACKLOG, 1024 BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最 ...

  3. Codeblocks自动代码格式化+快捷键

    Codeblocks自动代码格式化+快捷键 - u010112268的博客 - CSDN博客 https://blog.csdn.net/u010112268/article/details/8110 ...

  4. FFMPEG推流到RTMP服务器命令 - weixin_37897683的博客 - CSDN博客 https://blog.csdn.net/weixin_37897683/article/details/81225228

    FFMPEG推流到RTMP服务器命令 - weixin_37897683的博客 - CSDN博客 https://blog.csdn.net/weixin_37897683/article/detai ...

  5. 洛谷 P4145 上帝造题的七分钟2 / 花神游历各国

    洛谷 这题就是区间开根号,区间求和.我们可以分块做. 我们记布尔数组vis[i]表示第i块中元素是否全部为1. 因为显然当一个块中元素全部为1时,并不需要对它进行根号操作. 我们每个块暴力开根号,因为 ...

  6. 一.MySQL入门基础

    1.关于cmd界面无法启动mysql: 1)必须要使用管理员身份运行cmd程序 2)如果下载MySQL5.7版本的,在windows服务上Mysql的名字默认是MySQL57,因此在cmd运行 net ...

  7. 搜狐云景client工具评測之WordPress的搭建

    搜狐云景是搜狐推出的一款PaaS产品,眼下还处在公測阶段,拿到邀请码后试用了一下,感觉还不错. 搜狐云景提供了四种方式部署应用,感觉应该能够满足各种口味的码农:1. zip包的形式在网页上传并部署   ...

  8. 查看Oracle的表中有哪些索引

    用user_indexes和user_ind_columns系统表查看已经存在的索引 对于系统中已经存在的索引我们可以通过以下的两个系统视图(user_indexes和user_ind_columns ...

  9. PyNest——part 3: connecting networks with synapses

    part 3: connecting networks with synapses parameterising synapse models NEST提供了各种不同的突触模型. 您可以使用命令nes ...

  10. 开博第一篇,学习markdown

    Markdown学习 其实之前自己也一直有记录,不过是Evernote记录,没有分享出来,最近看了一些牛人博客,觉得也应该分享出来.和别人多交流,多学习.所以花了几小时学了一下Markdown语法,现 ...