浏览 28297 次
锁定老帖子 主题:正确认识memcached的缓存失效
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-29
1、失效时间的计算: rel_time_t realtime(time_t exptime) { /* no. of seconds in 30 days - largest possible delta exptime */ if (exptime == 0) return 0; /* 0 means never expire */ if (exptime > REALTIME_MAXDELTA) return (rel_time_t) (exptime - stats.started); else { return (rel_time_t) (exptime+ current_time); } } 代码很简单,假如失效时间是120妙,那么计算后的失效时间就是120+current_time(当前时间和server启动时间差) 2、失效算法: item *do_item_get_notedeleted(const char *key, const size_t nkey, bool *delete_locked) { item *it = assoc_find(key, nkey); if (delete_locked) *delete_locked = false; if (it && (it->it_flags & ITEM_DELETED)) { /* it's flagged as delete-locked. let's see if that condition is past due, and the 5-second delete_timer just hasn't gotten to it yet... */ if (!item_delete_lock_over(it)) { if (delete_locked) *delete_locked = true; it = 0; } } if (it != NULL && settings.oldest_live != 0 && settings.oldest_live <= current_time && it->time <= settings.oldest_live) { do_item_unlink(it); // MTSAFE - cache_lock held it = 0; } [b]if (it != NULL && it->exptime != 0 && it->exptime <= current_time) { do_item_unlink(it); // MTSAFE - cache_lock held it = 0; }[/b] if (it != NULL) { it->refcount++; DEBUG_REFCNT(it, '+'); } return it; } 失效算法是通过比较it->exptime <= current_time来实现的,而it->exptime值,只有在cache值update的时候(set/add/replace)才回更新,仅仅get操作是不会更新这个时间的! 所以如果想让memcached正确的处理session的失效,必须在每次访问的时候, 引用 执行一次add操作(add操作当cache已存在时,仅仅更新exptime时间)
更正:昨天晚上又看了下代码,发现add操作如果cache已存在,并不更新exptime,仅仅刷新最后访问时间,所以应该使用set或replace操作。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-29
介绍完memcached的失效实现,再说说memcahced对于失效的cache内存回收时机,
对于失效的cache,严格来说,只有在get操作的时候,才真正回收(可供新的cache使用),网上流传的item_flush_expired()是用来处理过期失效的cache,是一种谬传,这个方法只有在flush_all是,也就是清空memcached所有缓存时,才会执行。 那么如果我们某个cache失效了,但之后我们就不再执行get操作了(比如session过期了),岂不是一直要占据我们宝贵的内存?答案是不一定,如果通过-M选项关闭了LRU算法,答案就是是,如果启用LRU算法,那么在给item分配内存的时候,LRU算法会正确回收失效的缓存。所以-M选项一定要慎用! 另外启用LRU算法时,一定要注意设置足够大的内存,否则未失效的session也可能被踢出。 |
|
返回顶楼 | |
发表时间:2007-05-29
PS:我自己是通过hack memcache的LRU算法,仅把失效的cache踢出,如果你也需要,可修改:
item.c的item_alloc方法: for (search = tails[id]; tries>0 && search; tries--, search=search->prev) { [b]if (search->refcount==0)[/b] { item_unlink(search); break; } } 增加条件:search->exptime && search->exptime <= current_time 另外还可以增加缺省失效时间,这可以通过修改memcahced.c的realtime方法,当exptime=0返回缺省的失效时间(单位为秒) |
|
返回顶楼 | |
发表时间:2007-05-29
balaschen 写道 if (exptime > REALTIME_MAXDELTA) return (rel_time_t) (exptime - stats.started); else { return (rel_time_t) (exptime- current_time); } 代码很简单,假如失效时间是120妙,那么计算后的失效时间就是120+current_time(当前时间和server启动时间差) 应该是减吧,120-current_time or 120-stats.started |
|
返回顶楼 | |
发表时间:2007-05-29
calmness 写道 balaschen 写道 if (exptime > REALTIME_MAXDELTA) return (rel_time_t) (exptime - stats.started); else { return (rel_time_t) (exptime- current_time); } 代码很简单,假如失效时间是120妙,那么计算后的失效时间就是120+current_time(当前时间和server启动时间差) 应该是减吧,120-current_time or 120-stats.started 是+代码我贴错了,已修改,贴成我hack过的代码,不好意思 另外,memchaced接受两种格式的失效时间,一种是当前时间,一种是失效时长(120就属于这种),如果是当前时间,执行return (rel_time_t) (exptime - stats.started);分支,结果依然是失效时长+current_time。 |
|
返回顶楼 | |
发表时间:2007-06-04
倒不如hack一下assoc.c里的assoc_insert方法,在方法的最前面加上一句
it->exptime += it->current_time; 提前更新exptime。在每次session.getAttribute("XXX")或cache.get("XXX")的时候先调一下mcClient.add("XXX",""); |
|
返回顶楼 | |