当前位置: 首页 > memcached, 缓存系统 > 正文

Memcached数据被踢(evictions>0)现象分析

关键字:
1 星2 星3 星4 星5 星 (2 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

很多同学可能熟知Memcached的LRU淘汰算法,它是在slab内部进行的,如果所有空间都被slabs分配,即使另外一个slab里面有空位,仍然存在踢数据可能。你可以把slab理解为教室,如果你的教室满了,即使别的教室有空位你的教室也只能踢人才能进人。
mc
本文介绍的却是另外一种现象。今天监控发现线上一memcached发生数据被踢现象,用stats命令看evictions>0,因为以前也出现过此问题,后来对这个参数增加了一个监控,所以这次主动就发现了。由于给memcached分配的内存远大于业务存储数据所需内存,因此初步判断是“灵异现象”。

第一步,netstat查看所有连接,排除是否被一些未规划的client使用,经排查后断定无此可能。

第二步,用tcpdump抽样检查set的指令,排除是否有忘记设cache过期时间的client,初步检查所有典型的业务都有expire time。

第三步,Google,未果

第四步,看源代码,了解evictions计数器增加时的具体细节,oh, no…

in items.c, memcached-1.2.8,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* do a quick check if we have any expired items in the tail.. */
int tries = 50;
item *search;
for (search = tails[id];
      tries > 0 && search != NULL;
      tries--, search=search->prev) {
      if (search->refcount == 0 &&
      (search->exptime != 0 && search->exptime < current_time)) 
      it = search;
    /* I don't want to actually free the object, just steal
     * the item to avoid to grab the slab mutex twice*/
    it->refcount = 1;
    do_item_unlink(it);
/* Initialize the item block: */
it->slabs_clsid = 0;
it->refcount = 0;
break;
}}

重复进行上述测试,未发生evictions。

9/8 Update: 注意到L108的tries=50没有?试想把测试第2步设置51条不过期数据到cache中,情况会怎样?因此新版的Memcached也同样存在本文描述问题。

几条总结:

过期的数据如果没被显式调用get,则也要占用空间。
过期的不要和不过期的数据存在一起,否则不过期的可能被踢。
从节约内存的角度考虑,即使数据会过期,也不要轻易使用随机字符串作为key,尽量使用定值如uid,这样占用空间的大小相对固定。
估算空间大小时候请用slab size计算,不要按value长度去计算。
不要把cache当作更快的key value store来用, cache不是storage。

本文固定链接: http://www.chepoo.com/memcached-data-was-kicked.html | IT技术精华网

Memcached数据被踢(evictions>0)现象分析:等您坐沙发呢!

发表评论