为什么要使用Memcache缓存数据
Memcache把数据缓存到内存里面去,读取速度非常快,如果我们把频繁访问的数据放到内存中,对提高整个平台性能和减轻数据库服务器压力效果是非常明显的。
Memcache服务器是独立的分布式服务,会在内存中建立hash列表,把数据存储为key-value的方式,能够从根本上提高数据访问速度。我们可以把Memcache理解为一个高效的数据中转站,是完全和WEB服务器、数据库服务器分开的,这样在扩展和部署上也就非常方便了。也就是说,我们在优化Memcache服务器或者更极端的Memcache服务器全部挂了,都不会影响平台的正常访问,真正的影响就是访问速度可能会慢下来,也会增加数据库服务器的压力。
如果我们把90%的时间里访问频繁的20%的数据存储到Memcache里面,将非常明显的提高访问速度,提升用户体验。
Memcache是非常成熟的缓存解决方案,技术成本及硬件成本也可以说是非常廉价的,所以在解决平台性能瓶颈上这绝对是个首要考虑的方案。
Memcache缓存实现的思路及核心代码
这里我们以信息列表为例,展示Memcache缓存实现的思路及应该注意的问题;
案例背景:
有一个信息表,里面有100万条信息,然而我们经常访问的是新的1000条。如果每页显示50条数据,那么就是新的前20页数据访问量非常大,需要缓存下来,后面的数据可以不用缓存,这个根据实际场景来分析。
1) 首先我们需要连接到Memcache服务器端,PHP有自己的扩展,直接使用:
//创建一个Memcache实例并连接到Memcache服务器
$hqmemcache = new Memcache;
//localhost是服务器地址,11211是端口
$hqmemcache->connect('localhost', 11211);
2) 然后就是数据的获取和输出过程:我们应该如何获取第一页数据那?
当然其它缓存页面也是这样操作的,原理完全一样;
参考代码:
//第$page页数据存储的key是:list_page_$page
$page = (isset($_GET['page'])&&(int)$_GET['page']) ? (int)$_GET['page'] : 1;
$pagenum = 50;
echo '<ul>';
//我们只缓存前20页(新的1000条数据)
$readfromdb = 1;
if($page <= 20){
$newslist = $hqmemcache->get('list_page_' . $page);
if($newslist){
//打印数据从哪里获取的,实际应用中删除即可
echo '从缓存读取的';
//如果有缓存数据直接打印
echo $newslist;
$readfromdb = 0;
}
}
/**
* 如果没有缓存数据(或者页数超过20),则去数据库获取数据
* 把获取过来的数据组装成字符串后存储到Memcache
* 只需要有一个访问者访问过就会缓存到Memcache
* 后面的所有访问者再访问时获取的就是Memcache里面的数据
*/
if($readfromdb){
$newslist = '';
$hqdb = new mysqli('localhost', 'root', '123456', 'testdata');
$result = $hqdb->query('SELECT * FROM newslist ORDER BY id DESC LIMIT '.$pagenum*($page-1).', ' . $pagenum);
while($news = $result->fetch_array(MYSQLI_ASSOC)){
$newslist .= '<li><A href="./content.php?id='.$news['id'].'" blank="_target">'.$news['kw'].'</A></li>';
}
echo $newslist;
//把数据存储到Memcache
if($page <= 20){
$hqmemcache->set('list_page_' . $page, $newslist);
}
}
echo '</ul>';
缓存的数据如何更新
我们应该在什么时间删除或更新缓存信息那?
这个过程也很简单,不需要太复杂的操作。就拿我们这个场景来讲,只需要在添加或更新信息时删除前20页所有的缓存即可。
那么重建缓存的代价有多大那?理想的讲就是第一个访问者访问时需要去数据库获取信息并生成缓存,全部缓存完也就是20页的数据获取,代价非常小,实际情况也和这个情况差距不大。
参考代码也很简单:
//有新消息添加或信息更新时删除缓存
for($di = 1; $di <= 20; $di++){
$hqmemcache->delete('list_page_' . $di, 0);
}
如果有一个用户缓存成功,那么后面100万个用户访问时就可以从Memcache获取了,这对减轻数据库服务器的压力效果是很明显的。
如有什么问题或者有什么更好的想法欢迎留言讨论哦!