2019独角兽企业重金招聘Python工程师标准>>>
2016-06-22 11:40:17.639591 2b067aa0e700 10 adding .rgw+.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611 to cache LRU end
2016-06-22 11:40:17.639593 2b067aa0e700 10 updating xattr: name=user.rgw.acl bl.length()=163
2016-06-22 11:40:17.639596 2b067aa0e700 20 get_obj_state: s->obj_tag was set empty
2016-06-22 11:40:17.639598 2b067aa0e700 20 Read xattr: user.rgw.acl
2016-06-22 11:40:17.639599 2b067aa0e700 20 Read xattr: user.rgw.idtag
2016-06-22 11:40:17.639600 2b067aa0e700 20 Read xattr: user.rgw.manifest
2016-06-22 11:40:17.639604 2b067aa0e700 10 cache get: name=.rgw+.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611 :type miss (requested=17, cached=22)
2016-06-22 11:40:17.639607 2b067aa0e700 20 get_obj_state: rctx=0x2b067aa0d0e0 obj=.rgw:.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611 state=0x2b06681eda90 s->prefetch_data=0
2016-06-22 11:40:17.639621 2b067aa0e700 20 rados->read ofs=0 len=524288
2016-06-22 11:40:17.640115 2b067aa0e700 20 rados->read r=0 bl.length=226
2016-06-22 11:40:17.640128 2b067aa0e700 10 cache put: name=.rgw+.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611
2016-06-22 11:40:17.640130 2b067aa0e700 10 moving .rgw+.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611 to cache LRU end
2016-06-22 11:40:17.640138 2b067aa0e700 10 chain_cache_entry: cache_locator=.rgw+im-core-prd-aa-s100-30
2016-06-22 11:40:17.640138 2b067aa0e700 10 chain_cache_entry: cache_locator=.rgw+im-core-prd-aa-s100-30
2016-06-22 11:40:17.640140 2b067aa0e700 10 chain_cache_entry: cache_locator=.rgw+.bucket.meta.im-core-prd-aa-s100-30:mzone.1461106.2611那我
异常分析:
异常点分析1:
在bucket创建失败后再次创建的情况下,日志显示:
cache_map中对应bucket的mzone元数据,名字存在,但对应的cache 实体信息为全0(怀疑,因为flags=0)
所以,引用cache put操作来更新它的mzone元数据时,因为entry里面的lru_iter指针的值实际上是0,代表NULL,与
lru中记录的lru.end不等
故而调用了对应的moving方法而不是adding方法
调用moving方法的时候,因为lru是list
再将新的name加入的lru队列
但是由于,entry.iter实际上是NULL,所以并没有移除什么东西,而name实实在在是加入了lru,不过lru.size的值却没有因此增加
就会出现lru记录的长度和实际的长度不等的情况。而adding操作的话不会出现这种情况。
修复方法1:
用list.contain判断lru中是否有该对象,有的话再删除:
list.contains("对象name"))
修改后代码:
函数:void ObjectCache::touch_lru
原代码:
else
{
ldout(cct, 10) <<"moving " <
lru.push_back(name);
lru_iter &#61; lru.end();
--lru_iter;
}
修改后&#xff1a;
else
{
ldout(cct, 10) <<"moving " <
{
lru.erase(lru_iter);
lru_size--;
}
lru.push_back(name);
lru_iter &#61; lru.end();
lru_iter--;
lru_size&#43;&#43;;
}
//lru.end不一定是NULL
修改目的&#xff1a; 保证lru的size和实际内容协调。如果lru_iter是空&#xff0c;那么就完全相当于新增。
但是这也不是问题的关键。
关键是&#xff0c;当lru_iter是空的时候&#xff0c;不应该将指针传入cache_lru函数&#xff0c;所以&#xff0c;需要改&#xff1a;
而且指针的&#43;&#43;和--操作的安全性也没有判断啊&#xff09;
在ObjectCache::touch_lru函数的去重操作后,adding或moving前&#xff0c;加入地址指针有消息判断&#xff1a;
if(lru_iter &#61;&#61; NULL)
{
ldout(cct,20) <<"ERR! entry name&#61;"<
}
异常分析2&#xff1a;
异常1出现的本质原因是cache_map中&#xff0c;mzone对应的name的实体entry是全0(怀疑&#xff09;&#xff0c;所以&#xff0c;排查cache_map中entry填充信rgw_cache_lru_size息。
那么&#xff0c;就是mzone的放入cache_map出了问题。。
放入&#xff1a;
1. cache put
放入lru_iter的信息正常情况是lru的末尾指针&#xff0c;
异常的话&#xff0c;如果cache_map中有值&#xff0c;但为0&#xff0c;就不等于end
entry就会是这个0&#xff0c;就是cache_map中有&#xff0c;但是全0
第一次&#xff1a;
指针&#61;lru的end&#xff0c;经过touch_lru后&#xff0c;指向lru的尾部&#xff0c;如果为0&#xff0c;说明&#xff0c;lru的尾部就是0了
注意&#xff1a;list的end指向的不是NULL&#xff08;可以不是&#xff09;&#xff0c;而是list中末尾元素的下一个&#xff0c;
而end地址--就是末尾信息
异常分析3&#xff1a;
lru_size与lru信息长度不一致时&#xff0c;会出现什么情况&#xff1a;排查&#xff1a;
1.touch_lru的去重过程中&#xff0c;若总长度大于配置长度rgw_cache_lru_size&#xff08;默认1000&#xff09;时&#xff0c;触发&#xff01;
操作&#xff1a;当lru_size大于设置值&#xff0c;并且&#xff0c;当前lru指针&#xff08;从头/最旧的开始&#xff09;不等于需要加入的name指针&#xff0c;那么修建cache_map&#xff0c;这里因为iter是从lru里面取出来的&#xff0c;做pop_front的时候&#xff0c;倒是真的可以不用判断的。
然而lru_size除了此次外&#xff0c;并没有做循环变量用&#xff0c;所以应该不会造成危害。
问题&#xff1a;
如果name还有需要处理的项&#xff0c;也就是在name之前的&#xff0c;但是没有有效使用&#xff08;&#xff09;
比如存盘&#xff0c;比如其他处理&#xff0c;怎么办&#xff1f;这就被清理了&#xff1f;
定位方式&#xff1a;
全局查找&#xff1a;removing entry: name&#61;看有没有对应的name
。。。。。
正常情况下&#xff0c;cache_map中的mzone应该已经存在了&#xff0c;那么&#xff0c;get的时候&#xff0c;获取name对应的entry就是存在的。
//int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cache_entry_info *cache_info)
待改进3&#xff1a;
cacahe中写入和修改元数据的时候有日志&#xff0c;怎么写入说数据的时候不打日志啊
日志啊。。很重要的啊
定位到&#xff1a;
写入数据的时候&#xff0c;已经将name加入了cache map 但是没有将元数据加入
get_obj_ref
---都是本地基本操作&#xff0c;失败的概率小&#xff0c;因为没有特定性&#xff0c;如
pool_create
open_bucket_pool_ctx
只可能是IO或者POOL创建失败
而且返回值&#61;不存在-EONET
最大可能性&#xff1a;
ObjectReadOperation操作执行失败
返回值&#61;不存在
rgw_rados_ref.ioctx.operate
*****************************
create_bucket
get_bucket_info
在循环中&#xff0c;必然是get_bucket_entrypoint_info
中返回的&#xff0c;但是该函数在之前被其他流程调用过
在获取实例信息的时候是OK的
get_bucket_instance_from_oid
get_bucket_instance_from_oid
rgw_get_system_obj
step1 int ret &#61; rop.stat(objv_tracker);
if (ret <0)
return ret;
store->stat_system_obj
RGWRados::get_obj_state_impl
raw_obj_stat
if (r &#61;&#61; -ENOENT)
{
s->exists &#61; false;
s->has_attrs &#61; true;
s->mtime &#61; 0;
return 0;
}
step2 因为在enoent的情况下&#xff0c;返回的是0&#xff0c;所以继续read
ret &#61; rop.read(0, request_len - 1, bl, objv_tracker);
进入get_system_obj第一步&#xff1a;执行get_obj_state
失败&#xff0c;返回
stat_system_obj在astate的exists为false的时候&#xff0c;也会返回enoent&#xff0c;所以。。这样也可以&#xff0c;可能会。。。
get_bucket_entrypoint_info
调入