Mmemcached的使用文档

编    写:袁    亮
时    间:2015-01-15
说    明:Mmemcached的使用文档

一、使用场景
1、在系统中,会有大量的比较耗时的重复计算,这会导致系统性能的急剧下降,为了解决该问题,我们希望将这些计算结果存下来,使得在一定时间内,直接获取结果就好。

2、例如:
一个首页,每天50W次访问,在首页上,有一个地方显示的是最近24小时内,回复数最多的10个用户,正常的取的话,我们需要取24小时内的所有回复,然后根据user_id进行groupby,并统计每个user_id对应的回复数,再根据回复数倒序,取前面10个,这会非常耗时间;
我们可以将计算出来的结果存储下来,在一定时间内(比如5分钟)内,直接返回这10个用户,那么这一块的系统性能提升接近:50W/24/(60/5)=1736倍(计算次数减少)

3、缓存技术在it的各个角落都能看到,是最基础的概念之一,不管是硬件、软件、互联网,都离不开它,是所有优化里第一个要接触的

二、常规使用方法
include_once("/opt/ci123/www/html/ci123libs/data/classes/hash/memcache/memcache.php"); //很多服务器上有

$key = "index_user_list";
$data = M::Get($key);
if($data !== false){ //没有设置值的时候,返回是false,flase本身设置到memcache里会变成空字符串
$data = '';//原有获取数据的逻辑
M::Set($key,$data,600);//将数据写入到Memcache中,并缓存600秒
}

三、缓存的两种基本形式
1、不精确,定时缓存
直接将结果,缓存到一定时间周期,过期则重新计算获取
优点:实现简单、效率高
缺点:源数据如果在缓存有效期内有更改,可能出现数据取出来是错误的
适用场景:对数据精确性要求不高
常见情况:浏览器静态缓存、nginx缓存、cdn缓存、dns缓存等等
Memcache缓存绝大多数都是这么使用

2、预先生成,精确缓存
当源数据有更改的时候,同时更改缓存中的数据
优点:数据精准
缺点:实现复杂,有些情况下甚至不可实现(与缓存本身违背,比如浏览器缓存)
适用场景:系统高度可控,并且对精度要求很高的情况
场景情况:mysql内部查询缓存、短链计算统计等
Memcache如果要使用这种的话,有一个比较简单的办法,在第一种做法的前提下,更新、删除等操作的时候,将相应的缓存删除,这样也能实现数据精确,而且实现简单。(不适用更新非常频繁的情况,否则缓存也白加了)

四、Memcached简单介绍
1、分布式的系统
2、纯内存缓存系统
3、key value结构的hashmap

五、避免出现的情况
1、存大key
场景:
比如我要缓存用户数据,有两种办法,一种是每一个用户一个key,里面对应的用户信息,uinfo_{$uid}
还有一种,我把所有用户信息写到一个key里,这样我只要一个key,节省了内存空间,uinfos
问题:
不要出现一个key里,存很大的数据,缓存粒度控制
但第二种其实是一个非常糟糕的设计,假设我有10W个用户,每个用户信息1Kb,那么这个key就将有100Mb
因此我每个页面取一次缓存,将会导致需要每次从memcache里取100M的数据,10个并发,内网千兆带宽就崩掉了

2、不要缓存执行次数很少的
场景:
有个统计,每天统计一下前一天的数据信息,大概要执行1分钟,太慢了,我要优化它,所以把他扔缓存里
问题:
这种就是一个非常典型的失败例子,缓存的数据后面压根不会用到,所有缓存能起效的前提,都必须是这个请求会是重复多次执行的

3、缓存可能不到时间就会失效(LRU替换算法,不要做精准的统计计算等操作)
场景:
记录页面的访问次数(精确的),因为mysql写太频繁导致锁严重,因此我把计数放在memcache里,很快,读取这些数据的时候我也通过memcache读取,一切都很美好。
问题:
某天你会突然发现,这统计数据不对啊,为什么昨天这个页面明明已经有5000多次了,今天怎么变300多了?而且缓存也没有过期啊,什么情况?
因为Memcahe会有内部的删除数据算法,在空间不够的情况下,会删除某些不常用的数据
解决办法:
持久层还是放在MYSQL里去实现,但可以把写合并,比如累加次数达到一定值的时候重新写回mysql,注意不要是定值重写,这会导致数据上涨的非常有规律,看起来很奇怪。
$num = M::Get("post_view_{$post_id}");
if($num > rand(10,30)){//平均20次更新写回mysql
//写回Mysql
//将memcache中的数字清空
}

4、Memcache不做持久化,服务重启,数据会全部丢失,启动的时候可能会导致数据库压力狂涨
如果项目很大的情况下,可能会出现挂掉之后数据库马上报警,又挂了
这个时候可以少量放开部分用户访问,然后慢慢加量,一般情况下不用管,直接硬抗几分钟就好了

5、命名 同一个系统里,不要出现两个同名的,会导致数据变的莫名其妙,统一管理
命名最好语意清晰,不会和别人写的导致重复
同一个Memcache的key管理,可以统一在一个文件里定义使用,防止因为key名重复导致逻辑出错

六、可视化 管理系统
MemAdmin
基于php和jquery开发,简单易用
http://192.168.0.249/memadmin/
admin fuyuan1906

七、Memcache本身的一些限制
1、最大过期时间30天(设置永久也无效)
2、最大键长128字节(不要取太长的,这个是会占内存空间的)
3、单个key的最大数据1M(一般不缓太大的数据,memcache的访问频率很高,如果单个key很大,带宽会非常高)
4、连接操作等无需验证,因此必须放在防火墙后面,只允许内网访问

发表评论