AI智能
改变未来

BlueStore checksum机制

BlueStore checksum机制
1.checksum的计算
2.checksum的验证

BlueStore 磁盘静默数据损坏分析

  1. fsck过程中发现磁盘数据静默错误
  2. clone操作
  3. read操作
  4. write操作
  5. Gc操作

实际场景
1.腾讯场景问题确认
2.rbd mirror
3.rbd export import
4.集群扩容

BlueStore checksum机制

Bluestore的checksum算法默认采用的是crc32, 算法的逻辑很简单,即以固定大小的数据块为单位进行计算checksum,数据块的大小一般为4K,同设备的块大小。
Checksum的结果作为bluestore_blob_t结构体序列化的一部分存放在数据库中,假设一个blob的长度为64KB,进行checksum的数据块大小为4KB, 则初始化该blob时,对于crc32,每个数据块的checksum用4字节描述,将分配(64KB/4KB)* 4 = 64字节用于存储该blob数据的checksum。

1.checksum的计算

写数据会进行checksum的计算,对于对齐写和非对齐写,都会以数据所在的4KB对齐的数据块为单位进行计算。比如0-256区间的数据更新,会将257-4095区间的数据读出来,然后以4KB为单位进行计算,如果257-4095原来不存在数据,则用0进行填充后进行计算,计算完将checksum值存储在该blob中。

2.checksum的验证

读数据时,bluestore中会首先查找所读取数据区间所对应的checksum数组,然后用读取的数据计算checksum,判断两者是否一致。举例如下:假设blob的大小为64KB,
本次读取的数据区间为8192~16383, 则分别计算8192~12287和12288-16383两个数据块的checksum,然后读取blob中之前写数据时计算的checksum,这两块数据对应的checksum值为checksum数组偏移为2和3的两个4字节变量。

BlueStore 磁盘静默数据损坏分析

BlueStore中如下五种操作会读取对象数据,其中目前只有对象数据read操作能主动触发对象修复操作,且对上层用户不感知。

结论:读数据的时候依靠checksum机制可以发现数据不一致的情况,其中read可以自动修复,其他的读取操作如果发现存在静默错误,会及时报错,所以可以取消定期deep-scrub操作。

1. fsck过程中发现磁盘数据静默错误

==>> int BlueStore::_mount(bool kv_only, bool open_db)
====>> fsck(cct->_conf->bluestore_fsck_on_mount_deep)
如果bluestore_fsck_on_mount_deep为真,bluestore的fsck过程中将会读取整个文件,以此将会检查该文件对应的磁盘块是否存在数据损坏现象,如果文件损坏,会导致mount失败,从而导致该osd启动失败。

//bluestore_fsck_on_mount_deep 默认为trueOption(\"bluestore_fsck_on_mount_deep\", Option::TYPE_BOOL, Option::LEVEL_DEV).set_default(true).set_description(\"Run deep fsck at mount\"),
2. clone操作

Clone操作是否从磁盘读数据取决于bluestore_clone_cow配置,如果bluestore_clone_cow为真,则直接进行extent的共享,不会有实际的数据读写操作。如果为假,读取被clone对象的数据,写入新的对象,如果此时读取过程中,发生磁盘静默错误,则直接assert,osd进程down掉。

//bluestore_clone_cow 默认为trueOption(\"bluestore_clone_cow\", Option::TYPE_BOOL, Option::LEVEL_ADVANCED).set_default(true).set_safe().set_description(\"Use copy-on-write when cloning objects (versus reading and rewriting them at clone time)\"),
3. read操作

读操作过程中,如果发现磁盘静默数据错误,是会主动对该对象进行修复的,代码调用流程如下:

==>> do_osd_ops====>> do_read======>> objects_read_sync======>> rep_repair_primary_object

将对象加入待修复列表,进行修复,读操作 会重新发起,用户不感知。

4. write操作

Write操作的rmw写,需要首先从磁盘读取数据进行覆盖写,如果此时发生磁盘静默错误,代码中直接assert,代码调用流程如下:
==>> _do_write_small
====>> _do_read 触发( assert(r >= 0 && r <= (int)tail_read);)

通常ext4类的本地文件系统会直接abort事务,将文件系统挂载为只读,因此此处直接assert osd,导致osd进程down也可以理解。

5. Gc操作

==>> _do_write
====>> _do_gc
======>> _do_read 触发assert(r == (int)it->length);
此处也会导致osd down,策略我理解同write操作。

实际场景

1.腾讯场景问题确认

1.1 cache?1.2 no crc? 1.3 migration?
ceph社区邮件”Copying without crc check when peering may lack reliability”提到的磁盘静默数据损坏没有及时发现的问题,根据发件人的测试步骤没有复现,数据都能自动修复,目前正在请求发件人提供完整复现脚本。现阶段调查结果如下:
1, ceph-objectstore-tool修改对象数据时,如果checksum使能,会同步用新的数据计算checksum,如果修改对象主副本,则新数据迁移到新的crush root下,此处是合理的,因为checksum检查通过,osd会认为数据是正确的,如果修改对象的从副本,由于迁移是根据主副本的数据,新的crush root下的数据仍然是主副本数据。
如果对该osd做deep-scrub, 如果对象所属的pg在该osd上是主pg,是能检测到数据变动的,因为会和从pg上的副本做对比,如果对象所属的pg在该osd上为从pg, deep-scrub将不会针对该pg做检查的。
2,如果对象数据的主副本存在cache,即使对应的底层硬件存在静默错误,正常的读操作和deep-scrub都不会检测到磁盘静默错误(我已经发送patch让deep-scrub能检测出此种损坏,patch已经被merge)。
3,数据迁移在ceph master分支上验证,在三副本测试中,破坏一个副本的数据,然后让数据迁移到另一个crush root下,ceph会自动进行数据修复的,用户不感知。

2.rbd mirror

测试步骤:
破坏journal对象的主副本数据,然后进行replay,待replay完成后检查两个rbd设备的数据是否一致。
测试结果:
暂时没有找到测试方法来控制上述流程,但理论分析是可以修复的,用户不感知道。Rbd-mirror回放日志数据,也就是读取日志对象主副本数据,具体流程同”3. read操作”。

3.rbd export import

测试步骤:
创建一个rbd设备,向其偏移0处写入4MB随机数据,然后通过dd破坏其中一段数据,注意破坏是主副本的数据。破坏完成后,将主副本所在的osd重启以消除cache的影响,然后进行rbd的export 和import测试,读取两个rbd设备的前4MB数据MD5值与初始的写入rbd设备的随机数据文件md5值是否一致。

测试结果:
损坏的rbd对象数据会自动进行修复,用户不感知,具体原理参见”3. read操作”。

4.集群扩容

测试步骤:
创建3 osd集群,用rados创建一个对象,损坏对象主副本数据,注意同样需要重启osd以清除bluestore层cache,加入3个新的osd,待集群稳定后,用rados读取对象数据,验证数据md5值是否一致。

测试结果:
集群rebalance成功,损坏的数据会自动进行修复,用户不感知,具体原理参见”3. read操作”。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » BlueStore checksum机制