memcache存储原理和命中率

刚开始接触memcache时,原公司有位大佬对我说“就是个缓存,没什么东西”,好吧,我查看了下命中率,70%还差点,汗颜。。。看来还是需要研究下的。

附: memcache状态查询代码

$memcache = new Memcache;
$memcache->connect("127.0.0.1",11211);
$status = $memcache->getstats();
echo '<pre>';
print_r($status);

会读到一堆数据,里面有几个重要的

Array
(
    [cmd_get] => 1  get命令(获取)总请求次数
    [cmd_set] => 1  set命令(保存)总请求次数
    [get_hits] => 1  总命中次数
    [get_misses] => 0  总未命中次数
    [limit_maxbytes] => 67108864  分配给memcache的内存大小(字节)
    [bytes] => 129  当前存储占用的字节数
    [total_items] => 1  服务器启动后存储的数据总数
    [evictions] => 0  为获取空闲内存而删除的items数
)

缓存命中率 = get_hits/cmd_get * 100%
get_misses的数字加上get_hits应该等于cmd_get
当内存未用完时,total_items = cmd_set

内存还有很大空间,命中率应该是99%以上。
为什么会这么低呢,这就不得不说memcache的存储机制

我们把存储空间比作房子,需要存放的数据比作人,memcache就是安居客,它把房子改造成隔间后出租。按照它的理解,根据租房需求来分配房间,如果是一个人,就住次卧,两个人就住主卧,三个人就住客厅,要是来一群人,直接整租,当然最多人数就取决于最大的房子(最大值是1MB)。

如果次卧已经住满了,又来一个人怎么办?,memcache觉得你一个人住主卧或者客厅太大了,就会把最长时间不用次卧的人踢掉,而宁愿让主卧和客厅空着。实际上memcache租了很多很多房子,第一套统一隔成很小,第二套隔开的比第一套大一点,第三套隔开的又比第二套大一点,以此类推到整个房子。

memcache的存储引擎,使用slabs来管理内存。内存先分成大小相等的slabs,然后每个slab被分成大小相等chunks,不同slab的chunk大小是不相等的。chunk的大小依次从一个最小数开始,按某个因子增长,直到达到最大的可能值。
如果最小值为400B,最大值是1MB,因子是1.20,各个slab的chunk的大小依次是:slab1 - 400B slab2 - 480B slab3 - 576B 以此类推

这样一来问题就清楚了,我存放的数据大小差不多,相当于都是一个人,那么当次卧不够时,会把人踢掉,而我看了下投票情况,访问数据比较平均,没有主次之分,这样内存未满也会命中丢失。

memcache中新的value过来存放的地址是该value的大小决定的,value总是会被选择存放到chunk与其最接近的一个slab中,如果你在启动memcache的时候没有追加-M(禁止LRU,这种情况下内存不够时会out of memory),那么memcache会把这个slab中最近最少被使用的chunk中的数据清掉,然后放上最新的数据。

解决办法也很简单,既然都是一个人,那就都隔成次卧好了。

预估我们的value大小并且适当的调整内存页大小和增长因子。memcached启动的时候,设定参数

-m:最大内存使用,单位MB,默认64MB。 可以调大点
-f:chunk增长因子,默认1.25。 改成1.1
-n:指定最小chunk的key+suffix+value大小。Item (no cas) 48,Item(cas) 56。当指定-C选项时,最小chunk为-n指定大小+48;当没有-C选项时,最小chunk为-n指定大小+56。

发布了5 篇原创文章 · 获赞 0 · 访问量 78

猜你喜欢

转载自blog.csdn.net/jy615183000/article/details/105276986