转自:https://www.ustack.com/blog/ceph-internal-recovery-and-consistency/

作为一个面向大规模的分布式存储系统,故障处理是作为一个常态异常处理。Ceph 为了细化和保证故障发生和故障恢复的集群高可用性和一致性,在设计上将故障分为两类:

  • 临时性故障: 主机升级维护,重启,掉电等等在一定时间内可以重新上线 OSD 的故障
  • 永久性故障: 作为强一致存储系统,状态只跟存储在持久设备的数据有关,因此这类故障主要就是盘损坏或者主机损坏并无法及时转移盘到另外主机。换句话说救是一定时间内无法将原来的 OSD 数据重新加入集群。

Ceph 将所有数据域划分成若干个 PG(Placement Group)管理,每个 PG 都存活在一个 OSD 节点上,因此 PG 是管理、恢复数据的主体。而 Monitor 节点不参与用户数据的任何操作,只提供了 PG 选举的协调作用。PG 所属数据的处理和恢复都由 PG 本身进行协调。

临时性故障

首先这里考虑临时性故障的处理,Ceph 引入了 PGLog 的概念,顾名思义,PGLog 由 PG 维护并且记录了该 PG 所有的操作,其非常类似于关系型数据库领域的 undo log,同时需要将 PGLog 与 Journal 概念划分清楚,Journal 是底层单机存储模块用来维护事务一致性的,它是数据库领域的 redo log。undo log 和 redo log 在数据库的作用与 Ceph 的 PGLog 和 Journal 作用是一致的。PGLog 通常只保存 PG 最近几千条的操作记录,但是在 PG 处于 Degraded 状态时,PGLog 会保存更多的日志条目期望能在故障 PG 重新上线后用来恢复数据。下面来简单描述故障发生导致 OSD 下线的流程:

  1. 某一个 OSD 下线
  2. 如果 OSD 主动下线它会通知 Monitor 自己下线,请做好相关通知工作。如果是异常下线,那么其他 OSD 和 Monitor 会通过 Heartbeat 来得知 OSD 下线同样让 Monitor 知晓
  3. Monitor 重新计算该 OSD 拥有的的 Primary PG,并将结果主动通知这些 PG 所在的 OSD
  4. PG 将自己设为 Degraded 状态后,将会减小自己的副本数,并增加保存的 PGLog 条目数

故障发生后,如果一定时间后重新上线故障 OSD,那么 PG 会进行以下流程:

1. 故障 OSD 上线,通知 Monitor 并注册,该 OSD 在上线前会读取存在持久设备的 PGLog,
2. Monitor 得知该 OSD 的旧有 id,因此会继续使用以前的 PG 分配,之前该 OSD 下线造成的 Degraded PG 会被通知该 OSD 已重新加入
3. 这时候分为两种情况,注意这个情况下 PG 会标志自己为 Peering 状态并暂时停止处理请求:
3.1 第一种情况是故障 OSD 所拥有的 Primary PG
3.1.1 它作为这部分数据"权责"主体,需要发送查询 PG 元数据请求给所有属于该 PG 的 Replicate 角色节点。
3.1.2 该 PG 的 Replicate 角色节点实际上在故障 OSD 下线时期间成为了 Primary 角色并维护了“权威”的 PGLog,该 PG 在得到故障 OSD 的 Primary PG 的查询请求后会发送回应
3.1.3 Primary PG 通过对比 Replicate PG 发送的元数据和 PG 版本信息后发现处于落后状态,因此它会合并得到的 PGLog并建立“权威” PGLog,同时会建立 missing 列表来标记过时数据
3.1.4 Primary PG 在完成“权威” PGLog 的建立后就可以标志自己处于 Active 状态 3.2 第二种情况是故障 OSD 所拥有的 Replicate PG
3.2.1 这时上线后故障 OSD 的 Replicate PG 会得到 Primary PG 的查询请求,发送自己这份“过时”的元数据和 PGLog
3.2.2 Primary PG 对比数据后发现该 PG 落后并且过时,比通过 PGLog 建立了 missing 列表
3.2.3 Primary PG 标记自己处于 Active 状态
4. PG 开始接受 IO 请求,但是 PG 所属的故障节点仍存在过时数据,故障节点的 Primary PG 会发起 Pull 请求从 Replicate 节点获得最新数据,Replicate PG 会得到其他 OSD 节点上的 Primary PG 的 Push 请求来恢复数据
5. 恢复完成后标记自己 Clean

第三步是 PG 唯一不处理请求的阶段,它通常会在 1s 内完成来减少不可用时间。但是这里仍然有其他问题,比如在恢复期间故障 OSD 会维护 missing 列表,如果 IO 正好是处于 missing 列表的数据,那么 PG 会进行恢复数据的“插队”操作,主动将该 IO 涉及的数据从 Replicate PG 拉过来,提前恢复该部分数据。这个情况造成的延迟大概在几十毫米,通常来说是可接受的。

永久性故障

上面的流程的前提故障 OSD 在 PGLog 保存的最大条目数以内加入集群都会利用 PGLog 恢复,那么如果在 N 天之后或者发生了永久故障需要新盘加入集群时,PGLog 就无法起到恢复数据的作用,这时候就需要 backfill(全量拷贝) 流程介入。backfill 会将所有数据复制到新上线的 PG,这里的流程跟上述过程基本一致,唯一的差异就是在第三步 Primary PG 发现 PGLog 已经不足以恢复数据时,这时候同样分为两种情况:

  1. 故障 OSD 拥有 Primary PG,该 PG 在对比 PGLog 后发现需要全量拷贝数据,那么毫无疑问 Primary PG 在复制期间已经无法处理请求,它会发送一个特殊请求给 Monitor 告知自己需要全量复制,需要将 Replicate PG 临时性提升为 Primary,等到自己完成了复制过程才会重新接管 Primary 角色
  2. 故障 OSD 拥有 Replicate PG,该 PG 的 Primary 角色会发起 backfill 流程向该 PG 复制数据,由于故障 OSD 是 Replicate 角色,因此不影响正常 IO 的处理

除此之外,恢复数据还需要涉及到恢复数据的带宽控制、优先级等细节问题,这里就不一一赘述了。

小结

总的来说,Ceph 的恢复模块设计原则是在保证数据强一致性的前提下,尽量细化恢复过程来提高数据可用性(请求能得到及时处理),这个细化过程势必带来了极大的复杂性,因此恢复模块实际上也是 Ceph 最复杂的设计之一,值得存储系统领域的开发者借鉴。

解析Ceph: 恢复与数据一致性的更多相关文章

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

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

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

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

  3. 解析 Ceph: FileJournal 的作用

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

  4. 解析Ceph: Snapshot

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

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

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

  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存储架构

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 本文是一篇Ceph存储架构技术文章,内容深入到每个存储特 ...

随机推荐

  1. Django模型中OneToOneField和ForeignKey的区别

    网上看到一篇讲解"Django模型中OneToOneField和ForeignKey区别" 的文章,浅显易懂; 可以把ForeignKey形象的类比为: ForeignKey是on ...

  2. k8s 常用命令

    [root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 1h v1.8.1 node1 ...

  3. (4.6)sql server索引缺失提示

    SQLSERVER如何查看索引缺失 sql server索引缺失提示 当大家发现数据库查询性能很慢的时候,大家都会想到加索引来优化数据库查询性能, 但是面对一个复杂的SQL语句,找到一个优化的索引组合 ...

  4. Android-实现切换Fragment页功能

    场景:使用Fragment实现切页. 类结构: 一:Activity Activity中使用getSupportFragmentManager().beginTransaction()来填充一个Fra ...

  5. 爬虫四 selenium模块详细参数

    selenium元素定位方法 一.访问页面并获取网页html from selenium import webdriver browser = webdriver.Chrome() browser.g ...

  6. Python 1 的数据类型

    Python3 中有六个标准的数据类型: Number(数字)String(字符串)List(列表)Tuple(元组)Sets(集合)Dictionary(字典) 1.Number(数字) pytho ...

  7. MySQL实验1: 新建一个名为 library 的数据库,包含 book、reader 两张表,根据自己的理解安排表的内容并插入数据。

    数据表(table)简称表,它是数据库最重要的组成部分之一.数据库只是一个框架,表才是实质内容. 实验: 新建一个名为 library的数据库,包含 book.reader两张表,根据自己的理解安排表 ...

  8. 在各种Linux发行版上安装Git的教程

    Git是一个流行的开源版本控制系统(VCS),最初是为Linux环境开发的.跟CVS或者SVN这些版本控制系统不同的是,Git的版本控制被认为是“分布式的”,某种意义上,git的本地工作目录可以作为一 ...

  9. python中的元类metaclass

    本文是一个转载的,因为原文写的太好了,所以直接copy过来吧. 原文请看:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上 很热的帖子.提问 ...

  10. mongodb GridFS django FileFiled 默认 widget 只有一个文件上传框显示不了字段内容,重写widget

    首先,定位到:FileFiled 默认 widget 源码:mongoadmin包options.py中,如下: # Defaults for formfield_overrides. ModelAd ...