1. Notes

a. 存储

  • 对象(必须通过 PG 间接地)归属于某个存储池,因此对象必须记忆其归属的存储池标识。
  • 作为文件系统中最经典的数据备份机制,快照和克隆对所有存储系统而言几乎都是必备功能。
  • 在 Ceph 中我们需要能够实现对 PG 中的每个对象进行严格排序,综合考虑这种排序使用的唯一标识需要使用哈希来实现。
  • 产生哈希冲突的概率一是取决于算法本身,而是取决于输出长度。在保证算法不变的前提下,增加输出长度可以不同程度地降低产出冲突的概率。
  • 使用命名空间加上对象名作为哈希输入而不是使用对象的全部特征值。基于这些排序算法可以对 PG 中的所有对象执行快速排序,这是实现 Backfill、Scrub 等复杂功能的理论基础。
  • 对象存储和我们常接触的硬盘和文件系统等存储形态不同,它有两个显著特征如下:
    • 对象存储采用 Key/Value(K/V) 方式的 RESTful 数据读写接口,并且常以网络服务的形式提供数据的访问;
    • 扁平的数据组织结构。对比文件系统,对象存储采用扁平的数据组织结构,往往是两层或三层。例如 AWS S3 和华为的 UDS,每个用户可以把他的存储空间划分为”容器“,然后往容器里放对象,对象不能直接放到用户的根存储空间里,必须放到某个容器的下面,而且不能嵌套,也就是说,容器下面不能再放一层容器,只能放对象。

b. CRUSH

  • 一致性哈希算法的出现解决了扩容带来的数据迁移问题,甚至能够接近理论上的最优解,但其模型仍过于简单,对于存储系统中的各种可能问题难以应对,其中最突出的就是数据失效问题。因为所有用户的数据都是均匀分布在系统重的,所以一个设备的失效将会影响所有用户数据的完整性。而且由于一致性哈希算法没有感知存储节点的实际物理分布的能力,如何合理地控制数据的失效域更是无从谈起。
  • Ceph 只需要在集群中维护并同步少量的 CRUSH 元数据(CRUSH Map, OSD Map和 CRUSH Rule),各个节点就能独立计算出所有数据的位置,并能保证数据结果对于同样的输入 xx 是相同的。并且 CRUSH 算法的计算过程无须任何中心节点的介入,理论上可以承受任何节点的失效问题。
    CRUSH 元数据包括如下几个:
    • CRUSH Map: 保存了集群中所有设备或 OSD 存储节点的位置信息和权重设置;
    • OSD Map: 保存了各个 OSD 的运行时状态。能让 CRUSH 算法感知存储节点的失效、删除和加入情况,产生最小化的数据迁移,提高 Ceph 在各种情况下的可用性和稳定性;
    • CRUSH Rule: 用户设置的规则;
  • 关于数据备份策略,通常来说多个数据副本是不需要有顺序的,但是纠删码不一样,纠删码的各个分片之间是需要有顺序的,所以对于 CRUSH 算法而言需要了解各个关联的副本之间是否存在顺序性。
  • Ceph 集群自动生成的默认规则只能保证集群数据备份在不同的主机中,实际情况更加复杂,需要用户根据失效域自行配置规则。

c. RADOS

  • OSD 和 Monitor 之间互相传递节点的状态信息,共同得出系统的总体运行状态,并保存在一个全局的数据结构中,即所谓的 Cluster Map 里。由 Monitor 负责与客户端交互来提供 Cluster Map,在客户端本地直接进行计算得到对象的存储位置,然后直接与对应的 OSD 进行通信。OSD 可以利用本地节点的 CPU 和内存执行那些传统集群架构中高耗CPU的任务,充分发挥节点上的计算能力;

d. OSD

  • 在 RADOS 中每个 OSD 也有自己的一个 Daemon,这个 Daemon 负责完成 OSD 的所有逻辑功能。OSD 在扁平的命名空间内把所有的数据存储为对象(也就是没有目录层次)。对象包含一个标识符、二进制数和由名/值对组成的元数据,元数据语义完全取决于 Ceph 客户端。
  • OSD 状态用两个维度表示:up 或 down(OSD Daemon 与 Monitor 连接是否正常);in 或 out(OSD 是否含有 PG)。
  • OSD 的状态检测使用心跳包,为了避免所有 OSD 都互相发送心跳包对集群性能产生影响,Ceph 选择 Peer OSD 发送心跳包。PeerOSD 是指该 OSD 上所有 PG 的副本所在的 OSD,根据 Public Network 和 Cluster Network 之分,Peer OSD 之间的心跳包也分为前端和后端,这样可最大限度地监测 OSD 及 Public Network 和 Cluster Network 的状态,及时上报 Monitor。

f. Others

  • 充分发挥存储设备自身的计算能力是 Ceph 系统设计的核心思想。
  • 不同于传统文件系统提供的 open/read/write/close/lseek,对象存储只提供 put/get/delete,对象存储的逻辑单元就是对象而不是我们通常概念中的文件;

2. Q & A

Q : Ceph 中分割出存储池的作用以及可以进行的操作都有哪些?

Ceph 抽象出存储池这个概念之后,便可以针对存储池设计特定的 CRUSH 规则,举例如下:

  • 限制其只能使用某些规格相同的 OSD;
  • 尽可能将所有数据副本分布在物理上隔离的、不同的故障域;
    也可以针对不同用途的存储池指定不同的副本策略,举例如下:
  • 若存储池承载的存储应用对时延敏感,则采用多副本备份策略;
  • 若存储的是一些对时延不敏感的数据(例如备份数据),为提升空间利用率则采用纠删码备份策略;
  • 其他还可以分别指定如独立的 Scrub、压缩、校验策略等

Q : 存储池的两次映射是什么?

存储池以 PG 为基本单位进行管理,RADOS 并没有将数据一步到位地写入 OSD 的本地存储设备,而是通过 PG 这个中间结构执行两次映射。
第一次映射是静态的,将任意类型的客户端数据按照固定大小进行切割、编号,作为伪随机哈希函数输入,均匀映射至每个 PG,以实现负载均衡策略;
第二次映射仍然伪随机哈希函数,以保证 PG 在 OSD 之间分布的均匀性,实现 PG 到 OSD 映射。但其输入除了全局唯一的 PG 身份标识之外,还引入了集群拓扑,并且使用 CRUSH 规则对映射过程进行调整,以帮助 PG 在不同 OSD 之间灵活迁移,进而实现数据可靠性、自动平衡等高级特性。

Reference

  1. Ceph存储(七)CephFS详解 | Andre’s Blogs (ngwind.github.io)