參數(shù)詳情
rgw gc max objs 垃圾收集器數(shù)據(jù)的分片數(shù),也可以理解為gc work數(shù) 32
rgw gc obj min wait 對象可被刪除并由垃圾回收器處理前最少等待多長時間 7200s
rgw gc processor max time 每次GCwork 執(zhí)行的最長時間 3600
rgw gc processor period 垃圾回收進程的運行周期 3600
有一個問題需注意:當(dāng)你gc隊列中有任務(wù),這時你強制減少rgw gc max objs數(shù)量,這時出現(xiàn)的結(jié)果:pool里面有數(shù)據(jù)殘留.
查看系統(tǒng)中的待gc的任務(wù):
[root@rgw-test ~]# radosgw-admin gc list --include-all
[
? ? {
? ? ? ? "tag": "54b4a9a0-ee4b-4cb7-8115-ace2272cb565.175310.41\u0000",//有待研究
? ? ? ? "time": "2018-11-08 17:41:48.0.010174s",//object可以被刪除的時間 ,由rgw gc obj min wait 和對象被rm操作的時間
? ? ? ? "objs": [
? ? ? ? ? ? {
? ? ? ? ? ? ? ? "pool": "default.rgw.buckets.data",
? ? ? ? ? ? ? ? "oid": "54b4a9a0-ee4b-4cb7-8115-ace2272cb565.175310.3__shadow_.xWHsehe8d0SY27B0wWK7Ueea0yW6xsQ_1",//object id 有待研究
? ? ? ? ? ? ? ? "key": "",
? ? ? ? ? ? ? ? "instance": ""
? ? ? ? ? ? }
? ? ? ? ]
? ? }
]
查看用于gc的pool和對象:
rados listomapkeys gc.$i --namespace gc -p default.rgw.log
rados listomapvals gc.$i --namespace gc -p default.rgw.log
就能看到對應(yīng)的分片以及對應(yīng)分片里面的內(nèi)容
使用場景:
? ? 1.用于刪除 abortmultipart遺留下的文件。
核心代碼:
Int abort_multipart_upload(RGWRados *store, CephContext *cct, RGWObjectCtx *obj_ctx, RGWBucketInfo& bucket_info, RGWMPObj& mp_obj)
{
??rgw_obj meta_obj;
??meta_obj.init_ns(bucket_info.bucket, mp_obj.get_meta(), RGW_OBJ_NS_MULTIPART);
??meta_obj.set_in_extra_data(true);
??meta_obj.index_hash_source = mp_obj.get_key();
??cls_rgw_obj_chain chain;
??list<rgw_obj_index_key> remove_objs;
??map<uint32_t, RGWUploadPartInfo> obj_parts;
??bool truncated;
??int?marker =?0;
??int?ret;
??do?{
????ret = list_multipart_parts(store, bucket_info, cct, mp_obj.get_upload_id(), mp_obj.get_meta(),?1000,
??????marker, obj_parts, &marker, &truncated);
????if?(ret <?0)
??????return?ret;
????for?(auto obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
??????RGWUploadPartInfo& obj_part = obj_iter->second;
??????rgw_obj obj;
??????if?(obj_part.manifest.empty()) {
????????string oid = mp_obj.get_part(obj_iter->second.num);
????????obj.init_ns(bucket_info.bucket, oid, RGW_OBJ_NS_MULTIPART);
????????obj.index_hash_source = mp_obj.get_key();
????????ret = store->delete_obj(*obj_ctx, bucket_info, obj,?0);
????????if?(ret <?0?&& ret != -ENOENT)
??????????return?ret;
??????}?else?{
????????store->update_gc_chain(meta_obj, obj_part.manifest, &chain);//更新gc隊列
????????RGWObjManifest::obj_iterator oiter = obj_part.manifest.obj_begin();
????????if?(oiter != obj_part.manifest.obj_end()) {
??????????rgw_obj head;
??????????rgw_raw_obj raw_head = oiter.get_location().get_raw_obj(store);
??????????rgw_raw_obj_to_obj(bucket_info.bucket, raw_head, &head);
??????????rgw_obj_index_key key;
??????????head.key.get_index_key(&key);
??????????remove_objs.push_back(key);
????????}
??????}
????}
??}?while?(truncated);
??/* use upload id as tag */
??ret = store->send_chain_to_gc(chain, mp_obj.get_upload_id() ,?false);?// do it async//把mp_obj發(fā)送給gc隊列
??if?(ret <?0) {
????ldout(cct,?5) <<?"gc->send_chain() returned "?<< ret << dendl;
????return?ret;
??}
??RGWRados::Object del_target(store, bucket_info, *obj_ctx, meta_obj);
??RGWRados::Object::Delete del_op(&del_target);
??del_op.params.bucket_owner = bucket_info.owner;
??del_op.params.versioning_status =?0;
??if?(!remove_objs.empty()) {
????del_op.params.remove_objs = &remove_objs;
??}
??// and also remove the metadata obj
??ret = del_op.delete_obj();
??return?ret == -ENOENT?-ERR_NO_SUCH_UPLOAD:ret;
}
2.用于http請求的abortmultipart
根據(jù)uploadid去刪除未上傳完分片
void?RGWAbortMultipart::execute()
{
??op_ret = -EINVAL;
??string upload_id;
??string meta_oid;
??upload_id = s->info.args.get("uploadId");
??map<string, bufferlist> attrs;
??rgw_obj meta_obj;
??RGWMPObj mp;
??if?(upload_id.empty() || s->object.empty())
????return;
??mp.init(s->object.name, upload_id);
??meta_oid = mp.get_meta();
??op_ret = get_multipart_info(store, s, meta_oid, NULL, attrs);
??if?(op_ret <?0)
????return;
??RGWObjectCtx *obj_ctx = static_cast<RGWObjectCtx *>(s->obj_ctx);
??op_ret = abort_multipart_upload(store, s->cct, obj_ctx, s->bucket_info, mp);//最終調(diào)用的是這個函數(shù)
}
3.使用客戶端刪除
int RGWRados::Object::Delete::delete_obj()
{
? RGWRados *store = target->get_store();
? rgw_obj& src_obj = target->get_obj();
? const string& instance = src_obj.key.instance;
? rgw_obj obj = src_obj;
? if (instance == "null") {
? ? obj.key.instance.clear();
? }
? bool explicit_marker_version = (!params.marker_version_id.empty());
? if (params.versioning_status & BUCKET_VERSIONED || explicit_marker_version) {
? ? if (instance.empty() || explicit_marker_version) {
? ? ? rgw_obj marker = obj;
? ? ? if (!params.marker_version_id.empty()) {
? ? ? ? if (params.marker_version_id != "null") {
? ? ? ? ? marker.key.set_instance(params.marker_version_id);
? ? ? ? }
? ? ? } else if ((params.versioning_status & BUCKET_VERSIONS_SUSPENDED) == 0) {
? ? ? ? store->gen_rand_obj_instance_name(&marker);
? ? ? }
? ? ? result.version_id = marker.key.instance;
? ? ? result.delete_marker = true;
? ? ? struct rgw_bucket_dir_entry_meta meta;
? ? ? meta.owner = params.obj_owner.get_id().to_str();
? ? ? meta.owner_display_name = params.obj_owner.get_display_name();
? ? ? if (real_clock::is_zero(params.mtime)) {
? ? ? ? meta.mtime = real_clock::now();
? ? ? } else {
? ? ? ? meta.mtime = params.mtime;
? ? ? }
? ? ? int r = store->set_olh(target->get_ctx(), target->get_bucket_info(), marker, true, &meta, params.olh_epoch, params.unmod_since, params.high_precision_time, params.zones_trace);
? ? } else {
? ? ? rgw_bucket_dir_entry dirent;
? ? ? int r = store->bi_get_instance(target->get_bucket_info(), obj, &dirent);
? ? ? if (r < 0) {
? ? ? ? return r;
? ? ? }
? ? ? result.delete_marker = dirent.is_delete_marker();
? ? ? r = store->unlink_obj_instance(target->get_ctx(), target->get_bucket_info(), obj, params.olh_epoch, params.zones_trace);
? ? ? if (r < 0) {
? ? ? ? return r;
? ? ? }
? ? ? result.version_id = instance;
? ? }
? ? BucketShard *bs;
? ? int r = target->get_bucket_shard(&bs);
? ? if (r < 0) {
? ? ? ldout(store->ctx(), 5) << "failed to get BucketShard object: r=" << r << dendl;
? ? ? return r;
? ? }
? ? if (target->bucket_info.datasync_flag_enabled()) {
? ? ? r = store->data_log->add_entry(bs->bucket, bs->shard_id);
? ? ? if (r < 0) {
? ? ? ? lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
? ? ? ? return r;
? ? ? }
? ? }
? ? return 0;
? }
? rgw_rados_ref ref;
? int r = store->get_obj_head_ref(target->get_bucket_info(), obj, &ref);
? if (r < 0) {
? ? return r;
? }
? RGWObjState *state;
? r = target->get_state(&state, false);
? if (r < 0)
? ? return r;
? ObjectWriteOperation op;
.....................
? ? int ret = target->complete_atomic_modification();//拋向gc進程
? ? if (ret < 0) {
? ? ? ldout(store->ctx(), 0) << "ERROR: complete_atomic_modification returned ret=" << ret << dendl;
? ? }
.......
? return 0;
}
int RGWRados::Object::complete_atomic_modification()
{
? if (!state->has_manifest || state->keep_tail)
? ? return 0;
? cls_rgw_obj_chain chain;
? store->update_gc_chain(obj, state->manifest, &chain);
? if (chain.empty()) {
? ? return 0;
? }
? string tag = (state->tail_tag.length() > 0 ? state->tail_tag.to_str() : state->obj_tag.to_str());
? return store->gc->send_chain(chain, tag, false);? // do it async
}
4.覆蓋寫(put一個已經(jīng)存在的對象)時,舊的對象片段需要gc掉。
int?RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_size,
???????????????????????????????????????????map<string, bufferlist>& attrs,
???????????????????????????????????????????bool assume_noent, bool modify_tail,
???????????????????????????????????????????void?*_index_op)
{
??RGWRados::Bucket::UpdateIndex *index_op = static_cast<RGWRados::Bucket::UpdateIndex *>(_index_op);
??RGWRados *store = target->get_store();
??ObjectWriteOperation op;
??RGWObjState *state;
??int?r = target->get_state(&state,?false, assume_noent);
??if?(r <?0)
????return?r;
??rgw_obj& obj = target->get_obj();
??rgw_rados_ref ref;
??r = store->get_obj_head_ref(target->get_bucket_info(), obj, &ref);
??r = target->prepare_atomic_modification(op, reset_obj, ptag, meta.if_match, meta.if_nomatch,?false, modify_tail);
??if?(r <?0)
????return?r;
??if?(real_clock::is_zero(meta.set_mtime)) {
????meta.set_mtime = real_clock::now();
??}
??if?(state->is_olh) {
????op.setxattr(RGW_ATTR_OLH_ID_TAG, state->olh_tag);
??}
??struct timespec mtime_ts = real_clock::to_timespec(meta.set_mtime);
??op.mtime2(&mtime_ts);
??if?(meta.data) {
????/* if we want to overwrite the data, we also want to overwrite the
???????xattrs, so just remove the object */
????op.write_full(*meta.data);
??}
??string etag;
??string content_type;
??bufferlist acl_bl;
??map<string, bufferlist>::iterator iter;
??if?(meta.rmattrs) {
????for?(iter = meta.rmattrs->begin(); iter != meta.rmattrs->end(); ++iter) {
??????const?string& name = iter->first;
??????op.rmxattr(name.c_str());
????}
??}
??if?(meta.manifest) {
????/* remove existing manifest attr */
????iter = attrs.find(RGW_ATTR_MANIFEST);
????if?(iter != attrs.end())
??????attrs.erase(iter);
????bufferlist bl;
????::encode(*meta.manifest, bl);
????op.setxattr(RGW_ATTR_MANIFEST, bl);
??}
??if?(!op.size())
????return?0;
??uint64_t epoch;
??int64_t poolid;
??bool orig_exists;
??uint64_t orig_size;
??if?(!reset_obj) {?//Multipart upload, it has immutable head.
????orig_exists =?false;
????orig_size =?0;
??}?else?{
????orig_exists = state->exists;
????orig_size = state->accounted_size;
??}
??bool versioned_target = (meta.olh_epoch >?0?|| !obj.key.instance.empty());
??bool versioned_op = (target->versioning_enabled() || is_olh || versioned_target);
??if?(versioned_op) {
????index_op->set_bilog_flags(RGW_BILOG_FLAG_VERSIONED_OP);
??}
??if?(!index_op->is_prepared()) {
????r = index_op->prepare(CLS_RGW_OP_ADD, &state->write_tag);
????if?(r <?0)
??????return?r;
??}
??r = ref.ioctx.operate(ref.oid, &op);
??if?(r <?0) {?/* we can expect to get -ECANCELED if object was replaced under,
????????????????or -ENOENT if was removed, or -EEXIST if it did not exist
????????????????before and now it does */
????if?(r == -EEXIST && assume_noent) {
??????target->invalidate_state();
??????return?r;
????}
????goto?done_cancel;
??}
??epoch = ref.ioctx.get_last_version();
??poolid = ref.ioctx.get_id();
...........
??r = target->complete_atomic_modification();//拋給gc隊列
??if?(r <?0) {
????ldout(store->ctx(),?0) <<?"ERROR: complete_atomic_modification returned r="?<< r << dendl;
??}
??r = index_op->complete(poolid, epoch, size, accounted_size,
????????????????????????meta.set_mtime, etag, content_type, &acl_bl,
????????????????????????meta.category, meta.remove_objs, meta.user_data);
............
??return?r;
上述代碼是在L版本代碼,gc在M版本進行了修改。use aio 的做法,性能能提神多少,有待研究。https://github.com/ceph/ceph/pull/20546
相關(guān)文檔連接
http://www.voidcn.com/article/p-phgisild-kd.html