本篇文章为大家展示了如何实现 ceph 原理分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
1 整体架构介绍 1.1 总体介绍
Ceph 是一种开源的软件定义存储系统,诞生于 2004 年,最早致力于开发下一代高性能分布式文件系统的项目。Ceph 可以部署在任意 x86 服务器上工作,具有良好的扩展性、兼容性和可靠性。它能对外提供文件系统服务 (cephfs)、块服务(rbd) 和对象存储服务(rgw),是一种统一存储系统。Ceph 架构支持海量数据存储,集群可以扩展至 PB 容量,系统本身无热点数据,数据寻址依赖计算而不是查找,并能做到数据状态自维护,数据自修复,是一款优秀的分布式存储系统。
1.2 整体架构
图 1 ceph 全景
Ceph 架构主要包含了:Rados 集群,librados 接口层,rgw、rbd 和 cephfs 这三种存储服务。
Rados 集群:Rados 是 Ceph 系统的核心,包含了分布式集群管理和数据管理,集群的扩展性和高可用性是在这里体现的。主要的组件有 monitor、osd 和 mds。Monitor 是集群的关键服务,它保证了集群元数据的一致性和集群的可服务性。Osd 是 ceph 的数据服务,它负责了业务数据的落盘,数据状态的监控,数据状态恢复,数据的迁移和恢复等流程。Mds 是 cephfs 的元数据服务,维护文件系统的超级块信息,目录结构,文件信息等。一般如果不使用 cephfs,是可以不用部署 mds 的。
librados 接口层:统一封装的接口层,提供集群连接接口,pool 创建接口,obj 读写接口等,作为基础库提供给上层调用,比如 librbd、libcephfs 和 librgw。第三方的应用可以直接调用 librados 对 ceph 做二次开发。
客户端:ceph 客户端包括 rbd、rgw、cephfs 这三种类型,同时也包括 librbd、libcephfs 和 librgw 这些开发库。对外提供存储服务,比如 rbd 可以导出 scsi 块设备,cephfs 可以 mount 到 Linux 主机上做为文件系统,也可以通过 cifs/nfs 导出为网络文件服务,rgw 对外直接提供 s3 或者 swift 对象存储服务。
2 集群管理 2.1 Monitor
Monitor 服务是 ceph 的核心服务之一,它主要作用是为整个集群提供全局的配置和系统信息。Ceph 集群其实是体现在 Monitor 集群上的,Monitor 是一个独立部署的服务,多个 Monitor 组成高可用集群。Monitor 采用 paxos 算法保证集群数据的一致性,Monitor 所管理的数据包括:
1、 Monitor Map:包括集群的 fsid,所有的 monitor 的 ip 和端口,以及 epoch
2、 OSD Map:包括集群的 fsid,所有 osd 状态及监听地址,pool 的信息及 pg 数等
3、 MDS Map:包括所有的 mds 服务的列表和状态,data pool 和 metadata pool
4、 PG Map:所有 pg 的信息,包括状态、version 等
5、 CRUSH Map:一个树形结构,包括存储设备,故障域等
2.2 心跳管理
Monitor 通过心跳这种方式来获得 OSD 服务的工作状态,根据这种状态的变化更新相应的位图。
首先是 OSD 之间会有心跳检查,OSD 会检查 osd_heartbeat_min_peers 个 OSD 服务,peer osd 其实是指的 osd 相邻的 osd 服务,默认是 10 个。这些相邻的 osd 服务首先是包含同一个 pg 的 osd 列表,这个是从 pg_map 上获取,如果得到的 osd 列表超过 osd_heartbeat_min_peers 个就丢弃,不足的就补上当前 osd 周围状态 up 的 osd 进来。
检查过程是每 osd_heartbeat_interval 秒就检查一次 peer 端的 osd,默认是 6 秒。如果 peer 端 osd 在 osd_heartbeat_grace 后没回复,默认 20s,则标记这个 osd 状态为 down。
图 2 osd peer 间心跳
在不同故障域之间 osd 的状态变化,monitor 可能不会第一时间感知到,这里设置了不同故障域的 reporter 个数,默认是 1
图 3 不同故障域的检查
图 3 所示,osd1 和 osd2 分属于两个不同的故障域。
如果一个 osd 不能和 peer 内的所有 osd 做心跳了,则会向 monitor 申请最新的 osd map。超时时间为 osd_mon_heartbeat_interval 默认 30s。
Monitor 如果在 mon_osd_report_timeout 内收不到 osd 的消息,则会设置 osd 为 down,mon_osd_report_timeout 默认为 900s。
正常情况下 osd 每隔 osd_mon_report_interval_min,(最短间隔时间默认为 5s)会向 monitor 报告一次事件,事件包括 start 刚启动、osd 故障、up_thru 的变化等。osd 向 monitor 报告的最长时间为 osd_mon_report_interval_max,默认为 120s。意思是说 120s 无论 osd 有没有状态变化都需要向 monitor 报告。
图 4 osd 向 monitor 报告
3 数据读写 3.1 OSD
OSD(object storage daemon)负责 Ceph 集群的数据读写,同时也负责向 Monitor 报告监控的 OSD 的状态。管理数据的迁移,副本,数据平衡,数据恢复。Ceph 集群数据管理的核心服务,通往磁盘的数据通道。
OSD 主要包含了两个主要组成部分,一个 PG,另一个是 ObjectStore。PG(placement group)是 Ceph 的数据管理的基本逻辑单位,参与数据读写,数据迁移,数据恢复等和数据相关的全部流程。ObjectStore 是负责向本地存储读写的模块,现在常用的是 filestore 和 bluestore,当前 onestor 版本使用的是 filestore。Filestore 实际上是操作的本地文件系统,将业务最终写到本地磁盘的文件中,默认是使用 xfs 文件系统。Bluestore 是直接操作的裸盘,数据直接通过 BIO 下到盘上,性能相较于 filestore 有较大提升,Ceph 的最新版本默认采用是 Bluestore。
3.2 读写流程
图 5 数据读写过程
数据要存储在 Ceph 上需要经历几个主要步骤:
1、 Client 需要获得 Monitor 最新的 cluster map,得到 map 后确定 osd 的信息
2、 对象到 pg 的 hash,具体为对待写的 object id 做 hash,得到的 hash 值,再对当前 pool 的 pg_num 取模,最后得到该对象所在的 pg id。
pg_id = hash(object_name) % pg_num
然后再将 pool id 加到 hash 值之前,比如 4.f1,4 就是 pool id,f1 是上面算出的 hash 值,这两部分构成一个 pg id。
3、 pg 到 OSD 的映射,数据最终需落盘,所以 pg 得映射到一个 OSD 上。这个映射过程采用的 Ceph 自己独有的 CRUSH 算法,通过计算选择一个合适 OSD。CRUSH 本质是一种伪随机算法。找到 OSD 后,Client 直接与 OSD 通信,建立网络连接,将数据发送到 OSD 服务处理。
4、 OSD 最后把收到的数据投递给 ObjectStore,由它完成向本地存储写入的过程。同时完成主从 OSD 的数据落盘。
OSD 的数据写入过程满足数据的强一致性,待所有数据落盘才向上返回。
图 6 主从 OSD 写入过程
1、 Client 先将写请求发到主 OSD 上。
2、 主 OSD 在收到 Client 请求后,立即向从 OSD 发送写请求,同时也写入主 OSD 的本地存储上。
3、 主 OSD 收到从 OSD 写入成功的 ack,再确认自己处理正确,最后再返给 Client 写完成 ack。写过程中必须等到所有的 OSD 的写成功返回才能向 Client 返回写操作成功的消息。
3.3 POOL 和 PG
Pool 是一种逻辑上存储资源池,Ceph 对外提供的存储服务,资源都是从 Pool 中划分提供的。Pool 分两种一种是副本模式,一种是纠删码模式。一个 Pool 是由许多 PG 构成的。Pool 的信息保存在 osd map 中。
PG 是对象数据的集合,同一个集合内的对象应用相同的存储策略。比如对象的副本都会存放到相同的 OSD 列表中。一个对象只属于一个 PG,一个 PG 包含多个对象,一个 PG 会存放到多个 OSD 上,一个 OSD 会承载多个 PG。
图 7 表示了一个 pool 是双副本,对象 t1 是怎么分布到 pg 1.3e 的。
图 7 pg 与 osd 对应关系
3.4 CRUSH 算法
CRUSH(control replication under scalable hash)算法是 Ceph 内部中重要的寻址算法,它主要解决对象到盘的寻址过程。同时由于是通过计算得出,因此集群不需要查询地址,所以也就没有中心节点的产生,极大的减少了元数据的体量。CRUSH 可以将数据尽量的分散到各个存储上。
CRUSH 算法主要使用的场景:数据 io 的时候,创建 pool 的时候,osd 状态 up/down,osd 的添加和删除。3.2 节所描述的,CRUSH 主要是解决 PG 是如何映射到 OSD 列表的问题。用函数表示就是:
crush(pg.x) – (osd.1, osd.2, osd.3,….osdN)
图 8 CRUSH Map
CRUSH map 可以认为是数据中心的抽象,它的目的是寻找到合适的位置存放数据副本。CRUSH 内容包括了组织结构 Hierarchical CRUSH Map,副本选择规则 Placement Rules 以及容器 Bucket。
层级化 CRUSH Map,逻辑上看组织结构是个树形结构。包含 device 和 bucket,device 一般为 osd 服务作为叶子节点。bucket 作为设备的容器,一般为 CRUSH Map 中的普通节点。bucket 的类型有 osd(device),host,chassis,rack,row,pdu,pod,room,datacenter,region,root,这些类型描述了 CRUSH Map 中的存储位置。每个 bucket 包含多个 device。
Bucket Weight,权重是用来描述存储能力的指标。1T 大小表示为 1,采用双精度数表示。Bucket 的权重大小是包含子 bucket 或 device 的权重大小。
Placement Rules 决定了对象副本选择规则,它定义从哪些 bucket 或是 device 里去选择。这样可以定义不同的 pool 可以从不同的磁盘选择存放位置。
表格 1 bucket 定义
# buckets
host cvknode146 {
id -2 # do not change unnecessarily
# weight 2.160
alg straw2
hash 0 # rjenkins1
item osd.1 weight 1.080
item osd.3 weight 1.080
}
host cvknode145 {
id -3 # do not change unnecessarily
# weight 2.160
alg straw2
hash 0 # rjenkins1
item osd.0 weight 1.080
item osd.4 weight 1.080
}
host cvknode144 {
id -4 # do not change unnecessarily
# weight 2.160
alg straw2
hash 0 # rjenkins1
item osd.2 weight 1.080
item osd.5 weight 1.080
}
rack rack0 {
id -7 # do not change unnecessarily
# weight 6.480
alg straw2
hash 0 # rjenkins1
item cvknode145 weight 2.160
item cvknode144 weight 2.160
item cvknode146 weight 2.160
}
root partition0 {
id -5 # do not change unnecessarily
# weight 6.480
alg straw2
hash 0 # rjenkins1
item rack0 weight 6.480
}
# rules
rule partition0_rule {
ruleset 1
type replicated
min_size 1
max_size 10
step take partition0
step chooseleaf firstn 0 type host
step emit
}
rule partition0_ec_rule_1 {
ruleset 2
type erasure
min_size 3
max_size 20
step set_chooseleaf_tries 5
step set_choose_tries 100
step take partition0
step chooseleaf indep 0 type host
step emit
}
表 1 中描述的是 CRUSH Map 的定义的 Bucket,用树形图表示就是:
图 9 crush map 图形化
图 9 所示,root 作为 crush map 的入口,定义了 bucket rack0,其中包括 3 个 host,每个 host 包括了两个 device osd。bucket 的定义了随机选择算法为 straw2,hash 算法为 rjenkins1。这里的 hash 算法是用来计算随机值,随机选择算法是根据随机值判定选择 OSD。
表 1 中所定义的选择规则是 partition0_rule 和 partition0_ec_rule_1。规则原型如下:
rule rulename {
ruleset ruleset
type [replicated | erasure]
min_size min-size
max_size max-size
step take bucket-name [class device-class]
step [choose|chooseleaf] [firstn|indep] N bucket-type
step emit
}
ruleset:当前规则的 id
type:pool 的存储模式
min_size:如果 Pool 的副本数小于 min_size 则不使用这个规则
max_size:如果 Pool 的副本数大于 max_size 则不使用这个规则
step take bucket-name [class device-class]:
选择一个 bucket,一般是 root 类型 bucket,以这个为查询的输入,遍历这颗树。同时也可而已指定自定义的设备类型。
step choose firstn {num} type {bucket-type}:
深度优先选择 num 个 bucket-type 类型的子 bucket。
l If {num} == 0, choose pool-num-replicas buckets (all available).
l If {num} 0 pool-num-replicas, choose that many buckets.
l If {num} 0, it means pool-num-replicas – {num}.
如果 num 为 0 则选择和 pool 副本数一样的,num 大于 0 小于 pool 的副本数,则返回 num 个副本数,如果 num 小于 0,则返回 pool 副本数减 num 的个数。
step chooseleaf firstn {num} type {bucket-type}:
和上一条规则一样,区别在于 chooseleaf 是选择叶子节点,一般就是 osd。
step emit:
输出选择结果。
3.4.1 Straw 算法
现在有了 crush 的组织结构 CRUSH Map 和选择规则 Placement Rules,从 bucket 中选出合适的设备是采用随机算法来做具体的选择。当前 CRUSH 所支持的随机算法有:
表格 2 随机选择算法
Uniform
适用于每个 item 权重相同,且很少添加或删除,item 的数量比较确定。
List
以链表保存 item,包含的 item 可以是任意权重,但是会造成某些节点被选中的概率变大。
Tree
采用 2 分查找树,包含大量 item 的情况下可以快速查找,但是会造成某些节点被选中的概率变大,而在节点删除添加移除和重新修改权重会引入额外组织变动开销,查找速度 O(logn)。
Straw
相对 List 和 Tree 是比较公平的算法,每个节点都有公平竞争的机会,而且权重越大的节点被选中的机会越大。
Straw2
Straw 的改进算法,减少了在节点删除移动的时候数据迁移量。
具体描述 Straw 算法,提供各个 bucket 尽量公平的选择机会,权重越大选中的概率越高。执行过程其实递归遍历 bucket,找到合适 device。如果权限大就尽量找权限大的,如果权限一样则随机返回。
图 10 straw 代码片段
如代码所示:
1、 crush(pg_id, osd_id, r) = draw,r 为常数,运算次数
2、 (draw 0xffff) * osd_weight = straw
3、 得到最大的 high_draw,返回该 item
其中 draw 就是随机数,然后用 draw 乘以权重得到一个签值,选中最大签值的 OSD。要保证不能每次都选中权重最大那个,随机数的产生就很重要。
图 11 rjenkins hash 算法
将 3 组数据传入进行混合搅拌,尽量得到一个随机值。可以看到只要传入的值是相同的,得到随机值也是相同的,所以 CRUSH 是一个伪随机的算法。
参考源码 src/crush/mapper.c,入口函数 crush_do_rule
3.5 ObjectStore 模块
ObjectStore 是 Ceph 系统落盘前的最后一个模块,它负责保证业务数据可以安全可靠高效的 IO。ObjectStore 定义事务操作,具体的本地存储必须实现这些操作。ObjectStore 目前包括 4 种本地实现:
1、 FileStore:H、J 版本使用较多的本地存储,采用文件系统做为对象读写的方式。
2、 BlueStore:最新 L 版本支持的本地存储,未来 Ceph 的默认方式,抛弃掉文件系统直接操作块设备,性能最好。
3、 KStore:使用 KV 存储系统作为本地存储。
4、 MemStore:数据和元数据都保存在内存中,主要用于测试和验证。
目前用于生产环境的是 FileStore 和 BlueStore。
3.5.1 FileStore
FileStore 默认使用 xfs 文件系统保存数据。利用文件系统 POSIX 接口实现 ObjStore 的接口,每个对象在底层是以文件存在。
图 12 filestore 结构
FileStore 包含 FileJournal 和 DBObjectMap 两个模块,FileStore 为了提高 ObjectStore 写事务处理能力和原子性引入了 FileJournal。它相当于数据库的 WAL(write ahead log),为了保证每个写事务的完整性。它会使用 direct io 方式写到 journal 日志里,完成后再将事务提交到 FileStore 的队列中继续完成写操作,如果中途有发生 crash,OSD 在做 recovery 的时候会将日志恢复出来。
FileStore 写数据顺序是,先写 journal 然后再写盘上。Journal 写完后会返回给上层,但是要能 read ready 还是要等到数据落盘后才行,不过在大量小 io 随机写场景性能还是不错。FileStore 由于先写日志再写盘,所以有个写放大的问题。
DBObjectMap 是专门用来管理对象的属性的模块,有两种实现 xattr 和 omap。xattr 是用文件系统的扩展属性实现的,受限于文件系统扩展属性的长度限制,适合小量数据存放。omap 是采用 leveldb k- v 键值存储实现,如果属性大小超过 xattr 的限制,则可以存放到 omap 中。
3.5.2 Bluestore
图 13 bluestore 整体结构
Bluestore 为解决 filestore 在写数据前先写 journal 产生的写放大,并针对 ssd 做了相应的优化。Bluestore 直接操作裸盘,尽可能的避免文件系统(xfs、ext4)的开销。操作裸盘则盘空间管理由 allocator(默认是 BitmapAllocator)处理。Bluestore 在 io 过程中产生的元数据,元数据则存放到 rocksdb kv 数据库中。rocksdb 存数据依赖文件系统,但是 rocksdb 将底层系统相关的抽象为 env,用户程序只需要实现相应的接口就可以提供底层的系统的封装。Bluestore 实现了 BlueRocksEnv,并实现了 Bluefs 支撑 BlueRocksEnv。Bluefs 的日志和数据文件都是保存在裸盘上,和用户数据共享裸盘设备,也可以分开指定不同设备。
图 14 osd 设备数据分区
osd 目录分区:默认占用 100M,默认挂载 xfs 文件系统。提供基本的描述信息,包括 whoami(osd 编号),osd 的 type,osd 的魔术字,block 块设备入口等。
Block dev label 分区:默认占用 4K。存储 bluestore_bdev_label_t 结构体信息,包含 osd_uuid,块设备 size,设备描述信息,创建时间等。
Bluefs supper block 分区:默认占用 4K。存储 bluefs_super_t 结构体信息,包含 osd_uuid,version 和 block_size 等。
DB 数据分区:默认占用 MAX[1G,块设备总大小的 4%],保存 DB 数据和日志数据。
用户数据分区:默认占用剩余空间,存放用户业务数据。
元数据映射关系:
图 15 元数据映射关系
一个对象对应一个 onode,一个 onode 包含多个 extent,多个 extent 存放在一个或者多个 blob 里,每个 blob 又对应到多个 pextent,就是具体的物理块,这样就完成了 extent 到 pextent 的映射。
BlueStore 读过程比较简单,如果有预读标志则从 cache 里读,如果没命中则需要从盘上读出来并且添加到 cache 中。
Bluestore 写过程比较复杂,大致分为大写和小写。根据写入数据长度来确定是小写还是大写,通过对 min_alloc_size(blob 的最小分配大写默认 64K)取模,如果小于 64K 为小写流程,如果大于 64K 则为大写流程。
图 16 写场景
小写分为覆盖写和非覆盖写,其中非覆盖小写和大写没有写惩罚,先写数据然后改元数据。覆盖写场景会产生 WAL 日志,先要完成 WAL 日志处理落盘后,再写入业务数据。
整体来说性能比 filestore 提高不少。
4 数据 peering 和恢复
Ceph 系统中承担数据 IO 和数据恢复的基本逻辑单元叫 PG(Placement Group),PG 是 Ceph 中数据载体。可以理解 PG 为一个目录或者集合,包含了多个对象。
PG 有自己的状态,PG 健康度出现异常,状态会发生变迁,数据也会发生迁移。
active+clean:PG 的健康时的状态。
Degraded:降级状态,如果是双副本的配置,有个 osd 挂掉了,PG 就会进入这种状态。这种情况下 PG 还是可以提供 IO 服务的。
Recovery:一个 osd 出现故障下线了,但这时 pg 还是可读写的,当故障 osd 启动后,它所保存的数据比其他 osd 版本要旧这个时候就会产生 recovery,保证数据一致。
Remapped:如果 osd 下线是由于硬盘故障,这个时候就是永久性故障,需要再分配新 osd 做重新映射。选中新 osd 后,数据还是为空的,需要从正常的 osd 上将数据全量拷贝到新 osd 上,所以状态一般是 remapped+backfilling。
Peered:出现这种状态,是由于故障的 osd 数量过多,造成了 pg 不能读写了。这个状态可以理解为正常的 osd 在等待其他副本 osd 上线。
4.1 数据 peering 机制
Peering 过程是一个 PG 对应的一组 OSD 的状态达到一致的过程,PG 达到 active 时,peering 过程就完成了,但是 PG 对应的 OSD 上的数据并不一定完全一致。
PG 发生的场景:
n 系统初始化 OSD 启动重新加载 PG 或者创建 PG,会触发 PG 发起一次 Peering 过程。
n OSD 故障或 OSD 增加减少,会导致 PG 的 acting set 发生变化,PG 也会发起一次 Peering 过程。
peering 概念介绍
1、 acting set 和 up set
acting set 是一个 PG 活动的一组 OSD,该列表是有序的,下标第一个 OSD 为 prime OSD。up set 一般与 acting set 相同。不相同的情况是 OSD 故障导致,生成临时 PG。这个时候 acting set 和 up set 不一致。
2、 临时 pg
原 OSDacting set 列表中 [0,1,2] 的主 OSD osd.0 故障了,crush 重新选出的 acting set 为[3,1,2],但是这个时候 osd3 并没有该 PG 的数据,需要做 backfill,这个时候 osd3 是不能读的。所以会产生一个临时 PG 做为 prime,比如通知 monitor 让 osd1 做临时 prime,这个时候 up set 就为[1,3,2],acting set 还是[3,1,2],backfill 做完,临时 pg 取消,两个列表就想同了。
3、 Authoritative History 权威日志
指的是记录 pg 完整顺序的连续的操作日志记录,做为数据恢复的依据。
Peering 的过程,基本分为三个步骤
l GetInfo : pg 的主 osd 通过发送消息获取各个从 OSD 的 pg_info 信息。
l GetLog:根据 pg_info 的比较,选择一个拥有权威日志的 osd(auth_log_shard), 如果主 osd 不是拥有权威日志的 osd,就去拥有权威日志的 osd 获取,获取后主 osd 也拥有权威日志。
l GetMissing:拉取其它从 OSD 的 pg log(或者部分获取,或者全部获取 FULL_LOG) , 通过本地的 auth log 对比,来判别从 OSD 上缺失的 object 信息。以用于后续 recovery 过程的依据。
l Active: 激活主 osd,并发想通知 notify 消息,激活相应的从 osd。
简单来说 peering 并不恢复数据,只是将各个 osd 的状态统一起来,明确哪些对象需要恢复,为下一步做准备。
4.2 数据恢复
Peering 完成后,就可以知道是否有数据需要恢复了。恢复的方式有两种 recovery 和 backfill。
Recovery 是就根据 PG 日志中缺失的记录来修复不一致的对象。
Backfill 是 PG 通过重新扫描所有对象,对比发现缺失的对象,通过整体拷贝的方式修复。当 OSD 失效时间过长导致无法根据 PG 日志记录来修复,或者新 OSD 加入导致的数据迁移,这些都会导致 Backfill 流程。
5 数据端到端一致性
存储系统中 io 路径复杂,传统存储系统一般包括从应用层到内核文件系统、块设备、SCSI 层再到 HBA 和磁盘控制器,每层都有出错的可能。因此传统的端到端解决方案会以数据块校验为主来解决。
因为 Ceph 作为一个应用层的应用,这时候如果封装固定数据块并且加入校验数据会导致较严重的性能问题,因此 Ceph 在这方面只是引入 Scrub 机制 (Read Verify) 来保证数据的正确性。
简单来说,Ceph 的 OSD 会定时启动 Scrub 线程来扫描部分对象,通过与其他副本进行对比来发现是否一致,如果存在不一致的情况,Ceph 会抛出这个异常交给用户去解决。
Scrub 按照扫描内容不同分为两种方式:
n 一种叫 srub,它只是比较各个对象的副本元数据,来检查数据一致性。只是检查元数据,所以读取和计算的量都比较小,一种轻量的检查。
n 一种叫 deep-srub,它要进一步检查对象的数据内容是否一致,实现深度扫描,几乎要扫描磁盘上的所有数据并计算 crc32 校验,所有开销很大,占用系统资源很多。
Scrub 按照扫描的方式分为两种:
n 在线扫描:不影响系统正常业务。
n 离线扫描:需要系统停或冻结业务。
Ceph 的 Scrub 是实现了在线扫描,可不中断系统业务的前提下执行 scrub,但是针对具体某个对象做 Scrub,是会锁定对象的,阻止客户端对它的访问,一直到 Scrub 执行完成才会释放。
上述内容就是如何实现 ceph 原理分析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注丸趣 TV 行业资讯频道。