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

在阅读下文前务必先了解Ceph的基本情况和使用场景。Why Ceph and how to use 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://www.ustack.com/blog/ceph-snapshot/

解析Ceph: Snapshot的更多相关文章

  1. 解析CEPH: 存储引擎实现之一 filestore

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

  2. 解析Ceph: RBDCache 背后的世界

    转自:https://www.ustack.com/blog/ceph-internal-rbdcache/ RBDCache 是Ceph的块存储接口实现库 Librbd 的用来在客户端侧缓存数据的目 ...

  3. 解析 Ceph: FileJournal 的作用

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

  4. 解析Ceph: 数据的端到端正确性和 Scrub 机制

    转自:https://www.ustack.com/blog/ceph-internal-scrub/ Ceph 的主要一大特点是强一致性,这里主要指端到端的一致性.众所周知,传统存储路径上从应用层到 ...

  5. 解析Ceph: 恢复与数据一致性

    转自:https://www.ustack.com/blog/ceph-internal-recovery-and-consistency/ 作为一个面向大规模的分布式存储系统,故障处理是作为一个常态 ...

  6. Ceph源码解析:读写流程

    转载注明出处,整理也是需要功夫的,http://www.cnblogs.com/chenxianpao/p/5572859.html 一.OSD模块简介 1.1 消息封装:在OSD上发送和接收信息. ...

  7. ceph 初始化函数解析

    global_pre_init 预初始化函数,解析ceph.conf配置文件, 初始化定义global_context 和 config的全局变量. 全局预初始化函数 CINIT_FLAG_UNPRI ...

  8. 理解 QEMU/KVM 和 Ceph(1):QEMU-KVM 和 Ceph RBD 的 缓存机制总结

    本系列文章会总结 QEMU/KVM 和 Ceph 之间的整合: (1)QEMU-KVM 和 Ceph RBD 的 缓存机制总结 (2)QEMU 的 RBD 块驱动(block driver) (3)存 ...

  9. Ceph 的用户管理与认证

    目录 文章目录 目录 前言 Ceph 的用户管理 用户管理常规操作 CephX 认证系统 身份认证原理 使用 ceph-authtool 进行密钥环管理 注意事项 前言 常规的身份认证系统无非三点: ...

随机推荐

  1. reverse(), extend(), sort() methods of list

    >>> l = list('sdf') >>> l ['s', 'd', 'f'] >>> id(l) 4520422000 >>&g ...

  2. SQL利用Case When Then多条件判断

    CASE     WHEN 条件1 THEN 结果1     WHEN 条件2 THEN 结果2     WHEN 条件3 THEN 结果3     WHEN 条件4 THEN 结果4 ....... ...

  3. Aspose.Cells 读取Excel数据到DataTable

    C#代码: Workbook workbook = new Workbook(); workbook.Open(excelfile); Cells cells = workbook.Worksheet ...

  4. Intent(意图)

    Intent的中文意思是“意图,目的”的意思,可以理解为不同组件之间通信的“媒介”或者“信使”. 目标组件一般要通过Intent来声明自己的条件,一般通过组件中的<intent-filter&g ...

  5. myeclipse10添加jQuery自动提示

    首先先要在装上spket插件,这个网上有好多教程,我就不详细说了,主要说一下后面的设置,因为我发现我按照网上的装完也设置完没办法使用自动提示功能,以下是我根据前辈的经验然后自己摸索出来的: 选中所建的 ...

  6. hdu 3951(博弈规律)

    题意:给定围成一个圈的硬币n枚,然后每次可以取出连续的1-k枚,谁取完最后一枚谁就获胜. 分析:对于第二个人当第一个人取完后,他可以取成对称的形式,所以第二个人必胜. 代码: #include< ...

  7. c++中调用cygwin/x使用ncl

    1.C++中调用程序:   ShellExecute(NULL,L"open",L"cmd.exe",L"/c d: & cd cygwin ...

  8. 【LeetCode】165 - Compare Version Numbers

    Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...

  9. 在VS2103环境中集成Doxygen工具

    自己已将学习了两三次了吧,差不多这次该总结一下: Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,完全支持C.C++.Java.Objective-C和IDL语言,部分支持P ...

  10. js和jquery实现tab选项卡

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...