概述
在RWG的压力测试中,经常看到op的如下信息:”event”: “waiting for rw locks”
并且在RWG的压力很大时,这个waiting event会出现很多次,导致op的latency很高,所以需要分析下为什么会有这个waiting for rw locks的event?它与PG Lock的关系?
PG Lock
从 Ceph OSD op_shardedwq 中分析知道:
- OSD的
osd_op_tp
在处理OPRequest的时候就会先获取PG Lock; - OSD的
osd_op_tp
在调用OSD::dequeue_op()
返回后会释放PG Lock;
OSD::dequeue_op
的调用过程如下:
1 | OSD::dequeue_op() |
从上面的调用可以看出,OSD的osd_op_tp
里的线程处理过程在获取PG Lock后,只会把op组装为transaction后交给FileStore的work queue,然后就返回释放PG Lock了;
返回后写的数据可能还没有写到journal和disk,即还没有commit/apply成功;
所以针对同一个object的操作,虽说对它的操作有PG Lock,但也可能在PG Lock释放后,对object的实际操作RW还没有完成;
这就引入了object的读写锁,即struct ObjectContext
里的struct RWState
,通过它来互斥对同一object的读写,但允许对同一object的同时多读、同时多写(详细见下面RWState的分析);
对于同时多写,因为有PG Lock,所以多写并不会引起data consistency问题(PG Lock保证多写是顺序的),多个写提交到FileStore后可以并发或合并(待分析);
RWState
RWState
的定义
1 | struct ObjectContext { |
从上面的定义中看出,RW lock支持同时多读、同时多写;
在do_op
中,会根据op类型,尝试获取rw locks:
1 | /** do_op - do an op |
close_op_ctx
的调用关系如下:
1 | osd/ReplicatedPG.h |
系统调用close_op_ctx()
函数的地方有:
1 | 1 166 osd/ReplicatedPG.cc <<finish>> |
所以分析得出在op无论是出错、锁竞争、操作完成的情况下,都会调用close_op_ctx()
,它会把等待在object的RWState锁上的op重新入队处理;