Ceph快照的原理和实现
来源:互联网 发布:淘宝 5元红包 买什么 编辑:程序博客网 时间:2024/06/02 02:28
ceph的基本的特性之一,就是支持rbd的snapshot和clone功能。Ceph都可以完成秒级别的快照。
ceph支持两种类型的快照,一种poo snaps,也就是是pool级别的快照,是给整个pool中的对象整体做一个快照。另一个是self managed snaps. 目前rbd的快照就这类,用户写时必须自己提供SnapContex信息。
这两种快照时互斥的,两种不能同时存在。
无论是pool级别的快照,还是rbd的快照,其实现的基本原理都是相同的。都是基于对象COW(copy-on-write)机制。本文举例时都用rbd实例。
基本概念和数据结构
head对象:也就是对象的原始对象,该对象可以写操作
snap对象:对某个对象做快照后的通过cow机制copy出来的快照对象,该对象只能读,不能写
snap_seq or seq:快照序号,每次做snapshot操作,系统都分配一个相应快照序号,该快照序号在后面的写操作的实现发挥重要的作用。
snapdir对象:当head对象被删除后,仍然有snap和clone对象,系统自动创建一个snapdir对象,来保存SnapSet信息。
在rbd端,librados/IoCtxImpl.h 定义了snap相关的数据结构
struct librados::IoCtxImpl { ...... snapid_t snap_seq; ::SnapContext snapc; ......}struct SnapContext { snapid_t seq; // 'time' stamp vector<snapid_t> snaps; // existent snaps, in descending order}
SnapContext 数据结构用来在客户端(rbd端)保存Snap相关的信息。这个结构持久化存储在rbd的元数据中。
- seq 为最新的快照序号
- snaps 降序保存了该rbd的所有的快照序号。
IOCtxImpl里的 snapid_t snap_seq 一般也称之为snap_id, 如果open时,如果是snapshot,那么该snap_seq就是该snap对应的快照序号。否则snap_seq就为CEPH_NOSNAP(-2),来表示操作的不是快照。
struct SnapSet { snapid_t seq; //最新的快照序号 bool head_exists; //head对象是否存储 vector<snapid_t> snaps; // descending //所有的快照序号 vector<snapid_t> clones; // ascending //所有的clone的对象 map<snapid_t, interval_set<uint64_t> > clone_overlap; // clone对象之间overlap的部分 map<snapid_t, uint64_t> clone_size; //clone对象的size}
数据结构SnapSet用于保存server端,也就是OSD端与快照相关的信息。seq保存最新的快照序号,head_exists保存head对象是否存在,snaps保存所有的快照序号。clones保存所有快照后的写操作需要clone的对象记录。
这里特别强调的是 clones 和 snaps的区别。并不是每次打快照后,都要拷贝对象,只有快照后,有写操作,才会触发copy操作,也就是clone操作。
clone_overlap 保存本次clone和上次clone的 overlap的部分,也就是重叠的部分。clone后,每次写操作,都要维护这个信息。这个信息用于以后数据恢复优化等其他操作才会用在到,这里不涉及。clone_size 保存每次clone后的对象的size
SnapSet数据结构持久化保存在head对象的xattr的扩展属性中。
- 在Head对象的xattr中保存key 为”snapset”,value为SnapSet序列化的值
- 在snap对象的xattr中保存key为user.cephos.seq的 snap_seq 值
RBD快照的原理
Rbd创建快照
Rbd快照基本步骤如下:
- 向monitor 发送请求,获取一个最新的快照序号snap_seq
- 把该image该快照的 snap_name 和 snap_seq 保存到rbd的元数据中
在rbd的元数据里,保存了所有快照的名字和对应的snap_seq号,并不会触发OSD端数据的操作,所以非常快。
快照后的写
当对一个image做了一个快照后,要对该image写,由于快照,需要copy-on-write机制。
客户端写操作,必须带SnapContex结构,也就是需要带最新的快照序号seq和所有的快照序号snaps. 在OSD端,对象的Snap相关的信息保存在SnapSet数据结构中,当写操作发生时,需要做如下的处理。
规则1
如果head对象不存在,创建该对象并写入数据,用SnapContext相应的信息更新SnapSet的信息。也就是snapSet的seq值设置为SnapContex的seq值,SnapSet中的snaps的值,设置为SnapContex的snaps值
规则2
如果写操作带的SnapContex的seq值,也就是最新的快照序号小于SnapSet的seq值,也就是OSD端保存的最新的快照序号, 直接返回-EOLDSNAP的错误。
ceph客户端始终保持最新的快照序号。如果客户端不是最新的快照需要,可能的情况是,多个客户端的情形下,其它的客户端有可能创建了快照,本客户端有可能没有获取到最新的快照序号,需客户端更新为最新的快照序号。
ceph也有一套Watcher回调通知机制,当别的的客户端做了快照,产生了以新的快照序号,当该客户端访问,osd端知道最新快照需要变化后,通知相应的连接客户端更新最新的快照序号。如果没有及时更新,也没有太大的问题,客户端更新重新发起写操作。
规则3
如果写操作带的SnapContex的seq值 等于SnapSet的seq值,做正常的的读写。
规则4
如果写操作带的SnapContex的seq值 大于SnapSet的seq值:
- 用SnapContex的 seq和 snaps更新 SnapSet的的seq和snaps的值
- 对当前head对象做copy-on-write操作, clone出一个新的快照对象,该快照对象的snap序号为最新的序号,并把clone操作记录在clones列表里,也就是把最新的快照序号加入到clones队列中。
- 写入最新的数据到head对象中
示列1 快照写操作示列
如示列1所示:
- 在操作1里,第一次写操作,写入的数据为data1,SnapContext的初始seq为0, snaps列表为空, 按规则1,OSD端创建并写数据,用SnapContext的数据更新SnapSet中的数据。
- 在操作2里,创建了该rbd一个快照,名字为snap1, 并向monitor申请分配一个快照序号为:1
操作3里,写入数据data2,写操作带的SnapContext,seq为1, snaps列表为{1}, 在OSD端处理,此时SnapContext的seq大于SnapSet的seq,操作按照规则4:
- 更新SnapSet的seq为1,snaps更新为{1}
- 创建快照对象obj1_1,拷贝当前head数据data1到快照对象obj1_1(快照对象名字下划线为快照序号,ceph目前快照对象的名字中含有快照序号),此时快照对象obj1_1的数据为data1,并在clones中添加clone记录, clones={1}
- 向head对象obj1_head中写入数据data2
操作4,操作5连续分别做了两次快照操作,快照的名字为snap3,snap6,分配的快照序号分别为3,6 (在Ceph里,快照序号是有monitor分配的全局唯一,所有单个rbd的快照序号不一定连续)
- 操作6,写入数据data3,此时写操作带的SnapContext为,seq=6, snaps为{6,3,1}共三个快照。此时SnapSet的seq为1,操作按规则4:
- 更新SnapSet的seq为6,snaps为{6,3,1}
- 创建快照对象obj1_6,拷贝当前head数据data2到快照对象obj1_6,更新clones={1,6}
- 向head对象obj1_head中写入数据data3
快照的读
快照读取时,输入参数为rbd 的name和快照的名字。Rbd的客户端通过访问rbd的元数据,来获取快照对应的snap_id,也就是快照对应的snap_seq
在osd端,获取head对象保存的SnapSet数据结构。这个需要根据snaps和clones来计算快照所对应的正确的 快照对象。
例如在示列1中,最后的SnapSet ={seq=6, snaps={6,3,1},clones={1,6}, ……}, 这时候读取seq为 3的快照, 由于seq 为3 的快照并没有写入数据,也就没有对应的clone对象,通过计算可知,seq为3的快照和snap 为 6的快照对象数据是一样的,所有就读取obj1_6对象
可知,osd端根据SnapSet中保存的snaps和clones记录,不难推测具体快照对应的数据对象。
快照的rollback
快照的回滚,就是把当前的head对象,回滚到某个快照对象。 具体操作如下:
- 删除当前head对象的数据
- copy 相应的snap对象到head对象
快照的删除
删除快照时,直接删除SnapSet相关的信息,并删除相应的快照对象。需要计算该快照
是否被其它快照对象共享。例如在示列1中,obj1_6 是被 snap为3 和snap 为6 的对象共享,他们数据是相同的。当删除snap为6的快照时,不能直接删除obj1_6就需要计算,做相应的处理。
ceph的删除是延迟删除,并不直接删除。
- Ceph快照的原理和实现
- 管理ceph的pool(快照,回滚)
- 百度快照的原理
- HDFS的快照原理和Hbase基于快照的表修复
- ceph后端rbd,active的实例创建快照报错
- 基于Ceph快照的异地灾备设计
- 基于Ceph快照的异地灾备设计
- 基于Ceph快照的异地灾备设计
- 基于Ceph快照的异地灾备设计
- ceph log的实现
- oracle快照原理及如何实现生成快照
- ceph存储 ceph集群存储快照概念
- Oracle快照原理及实现总结
- Oracle快照原理及实现总结
- Oracle快照原理及实现总结
- Oracle快照原理及实现总结_2
- Oracle快照原理及实现总结
- Oracle快照原理及实现总结
- 上百个Android开源项目分享
- 安卓sdk等各种资源下载网站
- php7 一键安装
- 如何设置才能获得电脑蓝屏产生的转储文件啊
- 数据结构实验一(第3题)
- Ceph快照的原理和实现
- 编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。
- Android动画大总结
- Mysql 5.7.9 安装错误小记
- 数据库(SQL)之触发器(trigger)中如何获取表中数据(使用局部变量)
- android camera系统3A模式及其状态转换(一)
- placeholder 兼容问题
- OpenJudge_P1808 公共子序列(DP)
- 全选及全不选