注意
本文档适用于 Ceph 开发版本。
消息码开发者笔记
简介
本文档的每一章都解释了 Ceph 中消息码实现的一个方面。它主要基于示例进行解释,以展示如何工作。
从和向OSD读取和写入编码块
一个消息码存储池将每个对象存储为 K+M 个块。它被分为 K 个数据块和 M 个编码块。存储池配置为大小为 K+M,以便每个块都存储在活动集中的 OSD 中。块的等级作为对象的属性存储。
假设创建了一个消息码存储池,用于使用五个 OSD(K+M = 5),并能承受其中两个的丢失(M = 2)。
When the object NYAN containing ABCDEFGHI写入它时,消息码编码函数将内容分成三个数据块,简单地通过将内容分成三部分:第一个包含ABC,第二个DEF,最后一个GHI。如果内容长度不是 K 的倍数,内容将被填充。该函数还创建两个编码块:第四个包含YXY and the fifth with GQC。每个块都存储在活动集中的 OSD 中。块存储在具有相同名称(NYAN)但位于不同 OSD 上的对象中。必须保留块创建的顺序,并且除了其名称外,还将其作为对象的属性(shard_t)存储。块1包含ABC and is stored on OSD5,而块4包含YXY and is stored on OSD3.
+-------------------+
name | NYAN |
+-------------------+
content | ABCDEFGHI |
+--------+----------+
|
|
v
+------+------+
+---------------+ encode(3,2) +-----------+
| +--+--+---+---+ |
| | | | |
| +-------+ | +-----+ |
| | | | |
+--v---+ +--v---+ +--v---+ +--v---+ +--v---+
name | NYAN | | NYAN | | NYAN | | NYAN | | NYAN |
+------+ +------+ +------+ +------+ +------+
shard | 1 | | 2 | | 3 | | 4 | | 5 |
+------+ +------+ +------+ +------+ +------+
content | ABC | | DEF | | GHI | | YXY | | QGC |
+--+---+ +--+---+ +--+---+ +--+---+ +--+---+
| | | | |
| | | | |
| | +--+---+ | |
| | | OSD1 | | |
| | +------+ | |
| | +------+ | |
| +------>| OSD2 | | |
| +------+ | |
| +------+ | |
| | OSD3 |<----+ |
| +------+ |
| +------+ |
| | OSD4 |<--------------+
| +------+
| +------+
+----------------->| OSD5 |
+------+
When the object NYAN从消息码存储池读取时,解码函数读取三个块:块1 containing ABC,块3 containing GHI和块4 containing YXY并重建对象的原始内容ABCDEFGHI。解码函数被告知块2和5缺失(它们被称为丢失)。块5无法读取,因为OSD4是无法服务 (.
解码函数可以在读取三个块后立即调用:OSD2是最慢的,它的块不需要考虑。这种优化在 Firefly 中没有实现。
+-------------------+
name | NYAN |
+-------------------+
content | ABCDEFGHI |
+--------+----------+
^
|
|
+------+------+
| decode(3,2) |
| erasures 2,5|
+-------------->| |
| +-------------+
| ^ ^
| | +-----+
| | |
+--+---+ +------+ +--+---+ +--+---+
name | NYAN | | NYAN | | NYAN | | NYAN |
+------+ +------+ +------+ +------+
shard | 1 | | 2 | | 3 | | 4 |
+------+ +------+ +------+ +------+
content | ABC | | DEF | | GHI | | YXY |
+--+---+ +--+---+ +--+---+ +--+---+
^ . ^ ^
| TOO . | |
| SLOW . +--+---+ |
| ^ | OSD1 | |
| | +------+ |
| | +------+ |
| +-------| OSD2 | |
| +------+ |
| +------+ |
| | OSD3 |-----+
| +------+
| +------+
| | OSD4 | OUT
| +------+
| +------+
+------------------| OSD5 |
+------+
嵌入码库
使用Reed-Solomon,参数为 K+M,对象 O 通过将其分成块 O1、O2、… OM 并计算编码块 P1、P2、… PK 来编码。任何 K 个块都可以从可用的 K+M 个块中使用,以获得原始对象。如果数据块 O2 或编码块 P2 丢失,可以使用 K+M 个块中的任何 K 个块来修复它们。如果丢失的块超过 M 个,则无法恢复对象。
读取对象 O 的原始内容可以简单地通过 O1、O2、… OM 的连接来实现,因为插件正在使用系统码。否则,必须将块交给消息码库解码方法来检索对象的内容。
性能取决于编码函数的参数,并且也受调用编码函数时使用的包大小的影响(例如 Cauchy 或 Liberation):较小的包意味着更多的调用和更多的开销。
虽然Reed-Solomon被作为默认选项提供,但 Ceph 通过一个抽象API使用,该API设计为允许每个存储池选择实现它的插件,使用存储在去重编码配置文件.
$ ceph osd erasure-code-profile set myprofile \
crush-failure-domain=osd
$ ceph osd erasure-code-profile get myprofile
directory=/usr/lib/ceph/erasure-code
k=2
m=1
plugin=isa
technique=reed_sol_van
crush-failure-domain=osd
$ ceph osd pool create ecpool erasure myprofile
The 插件中的 key=value 对,并动态加载自目录,并预期实现int __erasure_code_init(char *plugin_name, char *directory)函数,该函数负责在注册表中注册一个从ErasureCodePlugin派生的对象。插件ErasureCodePluginExample读取:
ErasureCodePluginRegistry &instance =
ErasureCodePluginRegistry::instance();
instance.add(plugin_name, new ErasureCodePluginExample());
The ErasureCodePlugin派生的对象必须提供一个工厂方法,从中可以生成ErasureCodeInterface对象的具体实现。插件ErasureCodePluginExample读取:
virtual int factory(const map<std::string,std::string> ¶meters,
ErasureCodeInterfaceRef *erasure_code) {
*erasure_code = ErasureCodeInterfaceRef(new ErasureCodeExample(parameters));
return 0;
}
The 参数参数是设置在消息码配置文件中的key=value对的列表,在创建存储池之前。
ceph osd erasure-code-profile set myprofile \
directory=<dir> \ # mandatory
plugin=isa \ # mandatory
m=10 \ # optional and plugin dependent
k=3 \ # optional and plugin dependent
technique=reed_sol_van \ # optional and plugin dependent
Notes
如果对象很大,在内存中编码和解码它们可能不切实际。然而,当使用RBD一个 1TB 设备被分成许多个 4MB 的独立对象时RGW也会这样做。
编码和解码在 OSD 中实现。尽管它可以在客户端进行读写实现,但 OSD 在进行清理时必须能够自行编码和解码。
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.