https://blog.csdn.net/skdkjzz/article/details/51579432
https://blog.csdn.net/skdkjzz/article/details/52852076
https://blog.csdn.net/liu3612162/article/details/79389088
相关配置说明:
osd_min_pg_log_entries 正常情况下PGLog的记录的条数,
osd_max_pg_log_entries 异常情况下pglog记录的条数,达到该限制会进行trim操作
主要存储内容为pg_log_entry_t
,主要包括如下内容
op:对象操作 (modify,delete,clone,promote,clean,error…)
object:对象名称
eversion:当前操作的pg epoch以及对应的版本
简单介绍两个概念:
epoch是一个单调递增序列,其序列由monitor负责维护,当集群中的配置及osd状态(up,down,in,out)发生变更时,其数值向上加一。这一机制等同于时间轴,每次序列变化是时间轴上的点。这里说的epoch是针对osd的,具体到pg时,即对于每个pg的版本eversion中的epoch的变化并不是跟随集群epoch变化的,而是当前pg所在osd的状态变化,当前pg的epoch才会发生变化。
如下图:
根据epoch增长的概念,即引入第二个重要概念interval
因为pg的epoch在其变化的时间轴上并非是完全连续的,所以在每两个变化的pg epoch所经历的时间段我们称之为intervals。
pglog相关的主要数据结构如上:pg_info_t
,pg_log_t
,pg_log_entry_t
,存储在rocksdb中
如上图中关于pglog中的各个参数含义如下:
具体的pglog内容可以使用如下工具查看:
停掉运行中的osd,获取改osd的挂载路径,使用如下命令获取pg列表
ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-9/ --type bluestore --op list-pgs
获取具体的pg_log_t信息
ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-9/ --type bluestore --pgid 19.39s2 --op log
获取具体的pg_info_t信息
ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-9/ --type bluestore --pgid 19.39s2 --op info
ceph osd map pool_name obj_name_id
输出如下:
osdmap e2074 pool ‘tc_malloc_p1’ (19) object ‘obj1’ -> pg 19.6cf8deff (19.3f) -> up ([7,NONE,8], p7) acting ([7,NONE,8], p7)
其中可以看到obj1映射到了19.3f的pg上,能够看到改pg的up set和actiong set
确认pg所在osd
ceph pg dump pgs_brief |grep ^19|grep 19.3f
可以看到改pg的承载osd,再确认该osd所在的资源池
通过以上两步找到会落入到指定pg的对象,以该对象为名将指定文件put到资源池中
rados -p tc_malloc_p1 put obj1 test.file
从该pg所在的osd集合中任意选择一个down掉,查看写入的关于obj1的log信息
ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-9/ --type bluestore --pgid 19.3fs1 --op log|less
struct pg_log_t {
/*
* head - newest entry (update|delete)
* tail - entry previous to oldest (update|delete) for which we have
* complete negative information.
* i.e. we can infer pg contents for any store whose last_update >= tail.
*/
eversion_t head; // newest entry 同样通过我们以上使用工具追踪单个的pglog方式看到head指向最新的一条信息
eversion_t tail; // version prior to oldest 指向最老的pglog
protected:
// We can rollback rollback-able entries > can_rollback_to
eversion_t can_rollback_to;
// always <= can_rollback_to, indicates how far stashed rollback
// data can be found
eversion_t rollback_info_trimmed_to;
public:
// the actual log,实际的pglog entry,用链表形式进行存储
mempool::osd_pglog::list<pg_log_entry_t> log;
...
struct pg_info_t {
spg_t pgid;
eversion_t last_update; ///< last object version applied to store.
eversion_t last_complete; ///< last version pg was complete through.
epoch_t last_epoch_started; ///< last epoch at which this pg started on this osd
epoch_t last_interval_started; ///< first epoch of last_epoch_started interval
version_t last_user_version; ///< last user object version applied to store
eversion_t log_tail; ///< oldest log entry.
hobject_t last_backfill; ///指出需要进行backfill的位置 < objects >= this and < last_complete may be missing
bool last_backfill_bitwise; //一种对象间比对的方法,采用bitwise方式还是nibblewise方式进行比对 < true if last_backfill reflects a bitwise (vs nibblewise) sort
interval_set<snapid_t> purged_snaps;
pg_stat_t stats;//pg 状态信息
pg_history_t history;//集群状态历史
pg_hit_set_history_t hit_set;
//当前数据结构主要存储pg在进行peering/mapping过程的历史信息,包括一些状态机事件的时间点
struct pg_history_t {
epoch_t epoch_created; //pg被创建的时间点
epoch_t last_epoch_started; //集群最后一次进入start的时间,不一定和本地相等。
epoch_t last_epoch_clean; //集群中最后一次进入clean状态的时间
epoch_t last_epoch_split; // 集群中最后一次分裂的时间
epoch_t last_epoch_marked_full; // 标记为满,暂未分析
/**
* In the event of a map discontinuity, same_*_since may reflect the first
* map the osd has seen in the new map sequence rather than the actual start
* of the interval. This is ok since a discontinuity at epoch e means there
* must have been a clean interval between e and now and that we cannot be
* in the active set during the interval containing e.
*/
epoch_t same_up_since; // same acting set since 用来标识PG最近一个interval的起点
epoch_t same_interval_since; // same acting AND up set since 标识自该epoch开始,pg当前的up没有发生变化
epoch_t same_primary_since; // same primary at least back through this epoch.标识自该epoch开始,PG当前的primary没有发生过变化
//描述单个pglog 条目/事件的内容
struct pg_log_entry_t {
// describes state for a locally-rollbackable entry
ObjectModDesc mod_desc; //pglog当前条目的操作描述(mod、delete、)
bufferlist snaps; // only for clone entries 当快照克隆时使用
hobject_t soid; //标记一个对象
osd_reqid_t reqid; // caller+tid to uniquely identify request 标记一个唯一的请求
mempool::osd_pglog::vector<pair<osd_reqid_t, version_t> > extra_reqids;
eversion_t version, prior_version, reverting_to; //本操作版本,本操作的前一版本,回退版本
version_t user_version; // the user version for this entry 用户为此对象安排的版本
utime_t mtime; // this is the _user_ mtime, mind you 用户定义的时间
int32_t return_code; // only stored for ERRORs for dup detection针用于失败时的返回值,此值用于重复请求检测
__s32 op; //操作类型(见类枚举) modify,promote,clone,delete
bool invalid_hash; // only when decoding sobject_t based entries
bool invalid_pool; // only when decoding pool-less hobject based entries
主要是pg 从reset -> activte过程中的状态转换,其中包括pg从peering到activate 以及epoch变化时pg 状态恢复的处理流程
根据pg状态机我们可以看到pg状态恢复为active的过程需要区分Primary
和Replicated
两种,因为不论是pg还是osd的消息处理都是由primary
主导,再分发给从组件。
同时PGLog参与恢复主要体现在ceph进行peering的时候建立missing列表来标记过时数据,以便于进行对这些数据进行修复。故障的OSD重新上线后,PG就会标记为peering状态并暂停处理请求