注意

本文档适用于 Ceph 的开发版本。

CLAY 代码插件

CLAY(coupled-layer 的缩写)代码是一种纠删码,旨在在修复发生故障的节点/OSD/机架时,在网络带宽和磁盘 IO 方面实现显著节省。假设

d = 修复期间联系的 OSD 数量

如果 jerasure 配置为 k=8m=4,丢失一个 OSD 需要从 d=8 个其他 OSD 读取才能修复。恢复 1GiB(例如)需要下载 8 X 1GiB = 8GiB 的信息。

然而,对于 clay 插件,d 在以下限制范围内可配置

k+1 <= d <= k+m-1

默认情况下,clay 代码插件选择 d=k+m-1,因为它在网络带宽和磁盘 IO 方面提供了最大的节省。对于配置为 k=8m=4d=11clay 插件,当单个 OSD 发生故障时,将联系 d=11 个 OSD,并从每个 OSD 下载 250MiB,总共下载 11 X 250MiB = 2.75GiB 的信息量。下面提供了更通用的参数。当对存储信息量达到 TB 级别的机架执行修复时,这些好处是巨大的。

插件

磁盘 IO 总量

jerasure,isa

\(k S\)

clay

\(\frac{d S}{d - k + 1} = \frac{(k + m - 1) S}{m}\)

其中 S 是正在修复的单个 OSD 上存储的数据量。在上表中,我们使用了 d 的最大可能值,因为这将导致实现从 OSD 故障恢复所需的数据下载量最小。

纠删码配置文件示例

一个可用于观察减少带宽使用的配置示例

ceph osd erasure-code-profile set CLAYprofile \
   plugin=clay \
   k=4 m=2 d=5 \
   crush-failure-domain=host
ceph osd pool create claypool erasure CLAYprofile

创建 clay 配置文件

要创建一个新的 clay 代码配置文件

ceph osd erasure-code-profile set {name} \
     plugin=clay \
     k={data-chunks} \
     m={coding-chunks} \
     [d={helper-chunks}] \
     [scalar_mds={plugin-name}] \
     [technique={technique-name}] \
     [crush-failure-domain={bucket-type}] \
     [crush-device-class={device-class}] \
     [directory={directory}] \
     [--force]

其中

k={data chunks}

描述:

每个对象被分成 data-chunks 部分,每部分存储在一个不同的 OSD 上。

类型:

整数

必需:

是。

示例:

4

m={coding-chunks}

描述:

计算每个对象的 coding chunks 并将它们存储在不同的 OSD 上。编码块的数量也是在不丢失数据的情况下可以停止运行的 OSD 数量。

类型:

整数

必需:

是。

示例:

2

d={helper-chunks}

描述:

在恢复单个数据块期间请求发送数据的 OSD 数量。需要选择 d,使得 k+1 <= d <= k+m-1。d 越大,节省越多。

类型:

整数

必需:

否。

默认值:

k+m-1

scalar_mds={jerasure|isa|shec}

描述:

scalar_mds 指定了在分层构建中用作构建块的插件。它可以是 jerasureisashec 之一

类型:

String

必需:

否。

默认值:

jerasure

technique={technique}

描述:

technique 指定了在指定的“scalar_mds”插件中将选择的技术。支持的技术包括 jerasure 的 'reed_sol_van'、'reed_sol_r6_op'、'cauchy_orig'、'cauchy_good'、'liber8tion',isa 的 'reed_sol_van'、'cauchy',以及 shec 的 'single'、'multiple'。

类型:

String

必需:

否。

默认值:

reed_sol_van (适用于 jerasure, isa), single (适用于 shec)

crush-root={root}

描述:

用于 CRUSH 规则第一步的 crush 桶的名称。例如 step take default

类型:

String

必需:

否。

默认值:

default

crush-failure-domain={bucket-type}

描述:

确保没有两个块位于具有相同故障域的桶中。例如,如果故障域是 host,则不会有两个块存储在同一主机上。它用于创建 CRUSH 规则步骤,例如 step chooseleaf host

类型:

String

必需:

否。

默认值:

host

crush-device-class={device-class}

描述:

使用 CRUSH 映射中的 crush 设备类名称将放置限制为特定类的设备(例如,ssdhdd)。

类型:

String

必需:

否。

默认值:

directory={directory}

描述:

设置从中加载纠删码插件的 directory 名称。

类型:

String

必需:

否。

默认值:

/usr/lib/ceph/erasure-code

--force

描述:

覆盖具有相同名称的现有配置文件。

类型:

String

必需:

否。

子块的概念

Clay 代码能够节省磁盘 IO、网络带宽,因为它是一种矢量代码,并且能够以更精细的粒度(称为子块)查看和操作数据块内的数据。Clay 代码中一个数据块内的子块数量由下式给出

子块数量 = \(q^{\frac{k+m}{q}}\),其中 \(q = d - k + 1\)

在修复 OSD 期间,从可用 OSD 请求的帮助信息只是数据块的一部分。事实上,在修复期间访问的数据块内子块的数量由下式给出

修复子块数量 = \(\frac{sub---chunk \: count}{q}\)

示例

  1. 对于 k=4m=2d=5 的配置,子块数量为 8,修复子块数量为 4。因此,在修复期间只读取了数据块的一半。

  2. k=8m=4d=11 时,子块数量为 64,修复子块数量为 16。从可用 OSD 读取数据块的四分之一用于修复发生故障的数据块。

如何根据工作负载选择配置

在一个数据块的所有子块中,只读取了少数几个子块。这些子块不一定在数据块内连续存储。为了获得最佳磁盘 IO 性能,读取连续数据是有帮助的。因此,建议您选择条带大小,使子块大小足够大。

对于给定的条带大小(根据工作负载固定),选择 kmd,使得

子块大小 = \(\frac{stripe-size}{k sub-chunk count}\) = 4KB, 8KB, 12KB …

  1. 对于条带大小较大的大型工作负载,选择 k、m、d 很简单。例如,考虑条带大小为 64MB,选择 k=16m=4d=19 将导致子块数量为 1024,子块大小为 4KB。

  2. 对于小型工作负载,k=4m=2 是一个很好的配置,可以提供网络和磁盘 IO 方面的优势。

与 LRC 的比较

本地可恢复代码(LRC)也旨在在单个 OSD 恢复期间节省网络带宽和磁盘 IO。然而,LRC 的重点是使修复期间联系的 OSD 数量(d)最小化,但这以存储开销为代价。clay 代码的存储开销为 m/k。对于 lrc,除了 m 个奇偶校验块之外,它还存储 (k+m)/d 个奇偶校验块,导致存储开销为 (m+(k+m)/d)/k。claylrc 都可以从任意 m 个 OSD 故障中恢复。

参数

磁盘 IO, 存储开销 (LRC)

磁盘 IO, 存储开销 (CLAY)

(k=10, m=4)

7 * S, 0.6 (d=7)

3.25 * S, 0.4 (d=13)

(k=16, m=4)

4 * S, 0.5625 (d=4)

4.75 * S, 0.25 (d=19)

其中 S 是正在恢复的单个 OSD 上存储的数据量。

由 Ceph 基金会为您呈现

Ceph 文档是由非营利性 Ceph 基金会 资助和托管的社区资源。如果您希望支持这项工作和我们的其他努力,请考虑 立即加入