深入理解Ceph存储架构( 四 )
2.5.1 副本I/O和Ceph客户端一样 , Ceph OSD也是通过与Ceph mon交互来获取到最新的集群映射关系 。 Ceph OSD也使用CRUSH算法 , 但是用这个算法是用来计算对象的副本应该存储在什么位置(译者注: 客户端用CRUSH是用来找主OSD以及计算出Acting Set列表 , 而OSD用CRUSH则是主OSD定位对应的副本是谁) 。
在典型的写操作场景下 , Ceph客户端使用CRUSH算法计算对象所在的PG ID以及Acting Set列表中的主OSD , 当客户端将对象写到主OSD时 , 主OSD会查看这个对象应该存储的副本个数(例如 , osd_pool_default_size = n) , 然后主OSD根据对象ID、存储池名称、集群映射关系这些信息再根据CRUSH算法来计算出Acting Set列表中的从属OSD(译者注: 除列表中第一个OSD外 , 其它的都是从属OSD) 。
主OSD将对象写入从属OSD中 , 当主OSD收到从属OSD回复的ACK确认并且主OSD自身也完成了写操作后 , 主OSD才会给Ceph客户端回复真正写入成功的ACK确认 。
文章插图
通过有代表性的Ceph客户端(主OSD)执行数据复制的能力 , Ceph OSD守护进程相对的减轻了Ceph客户端的这一职责 , 同时确保了数据高可用以及安全性 。
注: 比较典型的就是主OSD和从属OSD在部署时会将故障域进行隔离(比如不同时配置到一个rack上或一个row上 , 亦或是同一个node上) 。 CRUSH计算从属OSD的ID也会考虑故障域信息 。
2.5.2 纠删码I/O纠删码实际上是一种前向错误纠正编码 , 这种编码会将K个数据块通过补充N个编码块的方式 , 将原始数据扩展为更长的消息编码 , 以便当N个数据块出现问题时数据依旧不会丢失 。 随着时间的推移 , 开发了不同的纠删编码算法 , 其中最早和最常用的算法之一是Reed-Solomon算法 。
可以通过等式 N = K + M 对这一算法进行理解 , 等式中 K 表示数据块的个数 , M 代表了编码块的个数 , 而 N 则是在 纠删编码 过程中创建的总的块的个数 。 值 M 可以简化为 N – K, 也就是说在计算原始的K个数据块时 N – K 个冗余块也一并需要计算出来 。 这种方法保证只要N个块中的K有效就可以访问所有原始数据 。 换句话说 , 即使有 N – K 个块出现了故障 , 对外提供服务的数据仍旧是没有问题的 。
例如配置(N=16 , K=10)或者纠删编码 10/16 , 10个基本的块(K)中会有额外补充的6个块( M = K-N, 如16-10 = 6 )。 这16个块(N)可能对应16个OSD 。 即使有6个OSD出现问题 , 原始文件也可以从这10个已经验证的数据块中重建恢复 。 这就意味着不会有任何的数据丢失 , 因此纠删码也具备比较高的容错能力 。
和副本存储池类似 , 纠删码存储池也是由up set列表中的主OSD来接收所有的写操作 。 在副本存储池中 , Ceph对PG中的每个对象在从属OSD上都会有一份一样的数据对象;而对于纠删码存储池来说 , 可能略有不同 。 每个纠删码存储池都会以 K+M 个块来存储每一个对象 。
对象(的数据内容)会被切分成 K 个数据块以及 M个编码块 。 纠删码存储池创建时也需要配置成 K+M 的大小(size)以便每个块都可以存储到Activtin Set列表中的每个OSD上 。 对象的属性存储这些块的等级 。 主OSD负责数据划分到 K+M 个块的纠删编码以及将这些编码信息发送到其它的OSD上 。 同时主OSD也会维护PG的权威日志(译者注: 权威日志实际是一种进度控制机制 , 尤其当某些节点出现问题时 , 可以根据权威日志进行数据的恢复) 。
例如 , 使用5个OSD (K + M = 5) 创建纠删码存储池 , 支持其中2个 (M = 2) 块的数据丢失 。
将对象写入纠删码存储池中的时候(比如对象名叫 NYAN , 内容为 ABCDEFGHI )纠删码计算函数会将对象的内容按长度平分成3个块(即 , 分成K个数据块) , 第一个块内容为 ABC,第二个块内容为DEF,第三个块内容为 GHI,如果块内长度不是 K 的倍数 , 那么平分后最后的一块所剩余的空位就会进行填充以使其长度为K(比如内容串为ABCDEFGHIJ , 则3个数据块内容依次为ABCD、EFGH、IJ.. , 最后的IJ长度不够就会填充);除了将内容按K切分外 ,纠删码函数也要创建另外2个编码块 , 即第4个块内容为 XYZ ,第5个块内容为 GQC。
这里的每一个块内容都对应Action Set列表中的一个OSD 。这些块有相同的名称都叫 NYAN , 但块存在不同的OSD中 。 除了名称之外 , 数据块创建的对应序号需要存储在对象的属性中( shard_t )。包括 ABC 内容的第一个块存储在 OSD5 上 , 而包括 YXY 内容的第4个块则存储在 OSD3 上 。
文章插图
- 启动|拼多多深入布局母婴产业带 补贴+直播启动“母婴产品溯源”行动
- RFID在冷链物流中的作用-RFID冷链资产管理解决方案
- 《深入理解Java虚拟机》:对象创建、布局和访问全过程
- 都说编程要逻辑好,如何理解这个逻辑
- 成长思维:我大哥对“道法术器”的理解,80%的人不懂
- Linux信号透彻分析理解与各种实例讲解
- 深入理解Netty编解码、粘包拆包、心跳机制
- 从底层理解this是什么
- 《深入理解Java虚拟机》:锁优化
- 不外|一发工资就转走,损失的是银行吗?原来我们都理解错了