snaptrim中的qos

snaptrim中的配置项

1
2
3
4
5
配置项	                               默认值	                    说明
osd_snap_trim_cost 1MB
osd_snap_trim_priority 5
osd_snap_trim_sleep 0 两次PGSnapTrim请求间休眠时间
osd_pg_max_concurrent_snap_trims 2 每个PGSnapTrim对应的Object数目

客户端删除快照

RBD块的快照数据包含两部分内容:一部分是存储块级别的快照元数据,保存在header对象的OMAP;另一部分是Object级别的快照信息,这部分又由保存在Object属性中的快照元数据和Clone Object两部分内容构成。Ceph删除这两部分内容的方式不同。

RBD客户端向OSD发送删除快照的消息

1
2
3
4
5
6
7
8
9
10
11
rbd::Shell::execute() --> rbd::action::snap::execute_remove() --> rbd::action::snap::do_remove_snap() --> librbd::Image::snap_remove2() --> librbd::snap_remove() --> librbd::Operations<librbd::ImageCtx>::snap_remove() --> Operations<I>::snap_remove() --> librbd::Operations<librbd::ImageCtx>::execute_snap_remove() --> librbd::operation::SnapshotRemoveRequest::send() --> cls_client::snapshot_remove() --> ... --> 发送op给rbd_header对象所在的Primary OSD

// OSD删除快照信息
cls_rbd::snapshot_remove() --> cls_cxx_map_remove_key() --> ReplicatedPG::do_osd_ops(CEPH_OSD_OP_OMAPRMKEYS)

// RBD客户端向Monitor发送删除快照的消息
librbd::operation::SnapshotRemoveRequest::send() --> SnapshotRemoveRequest<I>::send_release_snap_id() --> Objecter::delete_selfmanaged_snap() -->
Objecter::pool_op_submit() --> Objecter::_pool_op_submit() --> MonClient::send_mon_message()

// Monitor删除快照信息
OSDMonitor::prepare_pool_op() --> pg_pool_t::remove_unmanaged_snap() --> pg_pool_t::removed_snaps

对第一部分内容,RBD客户端直接向header对象所在的Primary OSD发送CEPH_OSD_OP_OMAPRMKEYS消息,立即删除。对第二部分内容,Ceph采用异步策略:先向Monitor节点发送删除快照的请求,Monitor回复后客户端即可退出,宣告快照已被删除。同时,Monitor修改OSDMap中和快照相关的数据构建OSDMap增量,并在适当的时候将新版OSDMap分发给相关OSD节点,OSD节点接收到新OSDMap后获得待删除快照,从而开始删除Object级别的快照信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
ReplicatedPG(PG)
|-- snap_trimq: interval_set<snapid_t> // 待删除的快照列表
|-- pool: PGPool
|-- cached_removed_snaps: interval_set<snapid_t> // 总的快照列表
|-- newly_removed_snaps: interval_set<snapid_t> // 一次更新中,新产生的待删除快照列表

// OSD处理MOSDMap消息,扫描PG向Peering队列投递NullEvt事件
OSD::handle_osd_map() --> C_OnMapCommit::finish() --> OSD::_committed_osd_maps() --> OSD::consume_map() --> PG::queue_null() --> PG::queue_peering_event()

// OSD Peer工作线程处理NullEvt事件
OSD::process_peering_events() --> OSD::advance_pg() --> PG::handle_advance_map() -->
1. PGPool::update() // 更新PGPool中待删除的快照列表
2. RecoveryState::handle_event(AdvMap) --> RecoveryState::Active::react(AdvMap)--> ReplicatedPG::kick_snap_trim() --> SnapTrimmer::process_event(KickTrim) // 更新snap_trimq,通知状态机开始删除快照对象

OSD分别在PG::snap_trimq和PGPool中保持了待删除快照列表,真正开始删除数据时从PG::snap_trimq中取快照。为什么要在两个地方保存待删除快照?估计考虑到了PG Recovery的不同状态,在PG切换到Active状态时会将PGPool中的待删除列表赋值给snap_trimq。如果更新OSDMap时,PG恰好处于Active状态那么将同时更新PGPool和snap_trimq。上面给出了更新OSDMap时更新待删除快照列表的流程。

同Recovery、Scrub一样,SnapTrim也是通过控制PGSnapTrim来间接控制快照删除的整体速度。一个SnapTrim默认对应删除两个对象的快照,由osd_pg_max_concurrent_snap_trims配置决定。