-
Ceph
快照的原理与实现
北京休伦科技有限公司
常涛
ceph
的基本的特性之一,就是支持
rbd
的
snapshot
和
clone
功能
。
Ceph
都可以
完成秒级别的快照。
ceph
支持两种类型的快照,
p>
一种是
pool
级别的快照,是给整个
p>
pool
中的对象整
体做一个快照。另一个
是
rbd
级别的快照的,
给单个
rbd
的
volume
做一个快照。
ceph
目前并没有给单独的对象做一个快照。
无论是
pool
级别的快照,还是
rbd
的快照,其实现的基本原理都是相
同的。都
是基于对象
COW
(
copy-on-write)
机制。本文举例时都用
< br>rbd
实例。
基本概念和数据结构
head
对象
:也就是对象的原始对象,该对象可以写操作
snap
对象
:对某个对象做快照后的通过
cow
机制
copy
出来的快照对象,该对象
只能读,不能写<
/p>
snap_seq or seq<
/p>
:快照序号,每次做
snapshot
操
作,系统都分配一个相应快照序
号,该快照序号在后面的写操作的实现发挥重要的作用。
在
rbd
端
,
librados/IoCtxImpl.h
定义了
snap
相关的数据结构
struct
librados::IoCtxImpl {
......
snapid_t
snap_seq;
::SnapContext snapc;
......
}
struct
SnapContext {
snapid_t seq;
// 'time' stamp
vector
snaps;
// existent snaps, in descending
order
}
SnapContext
数据结构用
来在客户端(
rbd
端)保存
Snap
相关的信息。这个结构
持久化存储在
r
bd
的元数据中。
?
?
seq
为最新的快照序号
snaps
降序保存了该
rbd
p>
的所有的快照序号。
IOCtxImpl
里的
snapid_t snap_seq
一般也称之为
snap_id,
如果
open
时,如果是
snapshot
,那么该
snap_seq
就是该
p>
snap
对应的快照序号。否则
snap_
seq
就为
CEPH_NOSNAP
(
-2
),来表示操作的不是快照。<
/p>
struct
SnapSet {
snapid_t seq;
//
最新的快照序号
bool
head_exists;
//head
对象是否存储
vector
snaps;
// descending
//
所有的快照序号
vector
clones;
// ascending //
所有的
clone
的对象
clone seq <
br>clone <
br>化等其他操作才会用在到,
map
interval_set
>
clone_overlap;
//
对象之间
overlap
的部分
map
clone_size;
//clo
ne
对象的
size
}
数据结构
SnapSet
用于保存
server
端,也就是
OSD
端与快照相关的信息。
保
存最新的快照序号,
he
ad_exists
保存
head
对象
是否存在,
snaps
保存所有的快
照
序号。
clones
保存所有快照后的写操作需要
clone
的对象记录。
这里特别强调的是
clones
和
snaps
的区别。并不是每次打快照后,都要拷贝对
象,只有快照后,有写操作,才会触发
p>
copy
操作,也就是
clone
操作。
clone_overlap
保存本次
clone
和上次
的
overlap
的部分,也就是重叠的部
分。
clon
e
后,每次写操作,都要维护这个信息。这个信息用于以后数据恢复优
这里不涉
及。
clone_size
保存每次
clone
后的对象的
size
p>
SnapSet
数据结构持久化保存在
he
ad
对象的
xattr
的扩展属性中。
?
?
在
Hea
d
对象的
xattr
中保存
key
为
”snapset”
< br>,
value
为
SnapSet
序列化的值
在
snap
对象的
xattr
中保存<
/p>
key
为
的
p>
snap_seq
值
RBD
快照的原理
Rbd
创建快照
Rbd
快照基本步骤如下:
1.
向
monitor
发送请求,获取一个最新的快照序号
snap_seq
2.
把该
i
mage
该快照的
snap_name
和
snap_seq
保存到
rbd
p>
的元数据中
在
r
bd
的元数据里,保存了所有快照的名字和对应的
snap_s
eq
号,并不会触发
OSD
端数据的操
作,所以非常快。
快照后的写
p>
当对一个
image
做了一个快照后,
p>
要对该
image
写,
由于快照,
需要
copy-on-
write
机制。
客户端写操作,必
须带
SnapContex
结构,也就是需要带最新的快照序号
seq
和
所有的快照序号
snaps.
在
OSD
端
,
对象的
Snap
相关的信息保存在<
/p>
SnapSet
数据
结构中,当写操作发
生时,需要做如下的处理。
规则
1
如果
head
对象不存在,创建该对象并写入数据,用
SnapContext
相应的信息更
新
SnapSet
的信息。
也就是
< br>snapSet
的
seq
值设置
为
SnapContex
的
seq
p>
值,
SnapSet
中的
< br>snaps
的值,设置为
SnapContex
的
snaps
值
规则
2
<
/p>
如果写操作带的
SnapContex
的
seq
值,也就是最新的快照序号小于
SnapSet
的
seq
值,也就是<
/p>
OSD
端保存的最新的快照序号
,
p>
直接返回
-EOLDSNAP
的错误。
p>
ceph
客户端始终保持最新的快照序号
。如果客户端不是最新的快照需要,可能
的情况是,
多个客户端
的情形下,
其它的客户端有可能创建了快照,
本客户端有
可能没有获取到最新的快照序号,需客户端更新为最新的快照序号。
ceph
也有一套
Watcher
p>
回调通知机制,当别的的客户端做了快照,产生了以新
的快照序号,
当该客户端访问,
osd
端知道最新快照需要变化后,通知相应
的连
接客户端更新最新的快照序号。
如果没有及时更新,
也没有太大的问题,
客户端
更新重新发起写操
作。
规则
3
如果写操作带的
SnapContex
的
seq
值
等于
SnapSet
的
seq
值,
做正常的的读写。
规则
4
如果
写操作带的
SnapContex
的
s
eq
值
大于
SnapSet
的
seq
值:
1.
用
SnapContex
的
seq
和
snaps
更新
SnapSet
的的
seq
和
p>
snaps
的值
2.
对当前
head
对象做
copy-on-
write
操作
,
clone
出一个新的快照对象,该快照对象的
snap
序号为最新的序号,并把
clone
操作记录在
clones
列表里,也就是把最新的快
照序号加入到
clones
队列中。
3.
写入最新的数据到
head
对象中
-
-
-
-
-
-
-
-
-
上一篇:操作系统安全实验报告
下一篇:通知书之装船通知日期