Home  >  Article  >  Backend Development  >  如何用缓存技术?

如何用缓存技术?

WBOY
WBOYOriginal
2016-06-20 12:43:411022browse

请教各位高手,例如我的index.php页面主要如下:
include("IncDB.php"); 
session_start () ;
$result=mysql_query("SELECT * FROM userlinks where id='a02' and userid=‘".$_SESSION['id']."’ order by datetime desc limit 1",$link);
$row = mysql_fetch_row($result);
echo "$row[1]"; 
echo"
"; 
echo "$row[2]";

mysql_close($link); 
?> 

每次用户登录后,都要从数据库里读数据,再显示出来,会比较慢,有没有什么方法如缓存技术,当信息无变化时,能直接从某页面调取,而 不用每次再从数据库查询,然后再显示出来。谢谢大家。


回复讨论(解决方案)

我自己在网上看,可以用缓存技术,但我还是不明白具体怎么做?还请指教。谢谢!

是 可以用缓存
不过你的缓存策略是什么
缓存到哪里
如何知道数据发生了变化

这些你思考过吗?

我不懂啊哥,没思考过。因为上面这个页面会根据不同 的用户,内容也会变化,我琢磨缓存放在网站肯定不行吧,要不得为每一个用户建一个缓存备用,是不是应该在客户端?数据发生变化,是不是可以让后台来校验,但网页主动刷新时,就能把最新信息显示出来?

我的需求就是找一个办法,使得用户在打开这个页面时,不用每次都从数据库提数据,那样确实比较慢,因为该页面提取的数据比较多。

您能帮我看看怎么弄呢?谢谢!

不过这个页面如发生变化,有两种情况,一个是后台管理时做调整,内容会变化,这个可能几个月才能有一次,可以忽略;二是,用户通过EDIT.php页面修改userlinks里面的数据,这时候,内容就要发生变化了。
另外,我能把某个页面,如EDIT.php缓存到客户端吗?我发现每次用户打开都特别慢。
不知道我说清楚没有,大神。

你可以存SQL的查询结果,储存到缓存里面

文件缓存。

<?php include("IncDB.php"); session_start () ;$cache_file = dirname(__FILE__).'/cache.file';$expire = 60;$cache_data = json_decode(file_get_contents($cache_file), true);if(!$cache_data || time()-$cache_data['expire']>$expire){    $result=mysql_query("SELECT * FROM userlinks where id='a02' and userid=‘".$_SESSION['id']."’ order by datetime desc limit 1",$link);    $row = mysql_fetch_row($result);    $cache_data = json_encode(array('data'=>$row,'expire'=>time()));}else{    $row = $cache_data['data'];}echo "$row[1]"; echo"<br>"; echo "$row[2]";mysql_close($link); ?> 

谢谢各位大神。很抱歉,我很水,看了半天没明白这代码的含义,能帮我解释一下么?另外,6楼的代码是不是就是5楼说的,存SQL的查询结果,储存到缓存里面?
我觉得要是能实现把查询的数据存到本地,然后每次从本地读取就能实现我说的功能了。

我自己猜,好像代码是给缓存规定了一个更新时间,时间内就缓存读取,否则就数据库。如果这样,就不对了,因为,用户会通过edit.php页面随时就某个内容修改好多次,但也可能几个月都不改一次。因此如果对缓存规定更新时间不行。是否应该在edit页面中增加更新缓存的代码,而index页面直接读取本地缓存就行?如果本地没有,就读数据库?

对了,我贴的代码有误,提取的数据是多行,没有limit 1。不好意思。

建议你使用memcache缓存(把SQL的查询结果放到服务器的内存里),如果用户在edit.php更新了数据,那么就把memcache里的缓存清掉,然后index.php去查询缓存时,if(memcache缓存不存在){使用SQL语句更新数据}。

sorry,大哥,我不会啊,怎么用memcache啊?我在网上看到有说用这个的,是在edit页面增加语句么?还是其他?我啥都不懂啊。不好意思,能告诉我是什么代码,写在哪里?原谅我的无知。

index.php:

include("IncDB.php"); session_start () ;//使用memcache对象$memcache = new Memcache;$memcache->connect('memcache主机地址', 11211); //memcache默认端口号是11211if(!$memcache->get('results')){	$result = mysql_query("SELECT * FROM userlinks where id='a02' and userid=‘".$_SESSION['id']."’ order by datetime desc", $link);	$row = mysql_fetch_row($result);	echo "$row[1]"; 	echo"<br>"; 	echo "$row[2]";	mysql_close($link); 	$memcache->set('results', $row);}


edit.php:
//在edit.php里,用户更新了数据,则清除memcache缓存。//用户更新数据代码.....$memcache = new Memcache;$memcache->connect('memcache主机地址', 11211); //memcache默认端口号是11211$memcache->delete('results', 0); //0表示该元素立即删除

既然 也可能几个月都不改一次,那么直接生成和使用静态页就是了,何必用什么缓存?

谢谢大神们。我回去试试。谢谢!
回xuzuning,是后台改,几个月才一次,但用户改,可能频率就高了。谢谢关心。

我追问一下misakaqunianx.,我不懂啊。1、根据您给的方法我提取数据比如有10条,缓存这10条数据后,如果用户后来改了其中的一条如第5条,也能通过EDIT页面的$memcache实现精确更新该条数据么?
2、在index页面中,哪一句是说从本地缓存提取数据的?我看不明白。
3、如果用户在本地有两个用户名,不会影响吧?
不好意思,问的太弱了。

谢谢大神们!

我追问一下misakaqunianx.,我不懂啊。1、根据您给的方法我提取数据比如有10条,缓存这10条数据后,如果用户后来改了其中的一条如第5条,也能通过EDIT页面的$memcache实现精确更新该条数据么?
2、在index页面中,哪一句是说从本地缓存提取数据的?我看不明白。
3、如果用户在本地有两个用户名,不会影响吧?
不好意思,问的太弱了。


只要你的用户修改了任意数据,你就把memcache的缓存清除掉,这样就可以保证不管修改了什么,都会重新用SQL查询数据库。
$memcache->get('results')是从内存里取出缓存(memcache不是文件缓存,而是放到服务器内存里缓存)
如果要使用memcache,需要开启memcache的扩展,方法就百度去吧。

我要是上传到空间里去,就不必要我还要增加您说的代码即可吧?再开启扩展了吧,服务商自己应该开好了吧,谢谢。

我要是上传到空间里去,就不必要我还要增加您说的代码即可吧?再开启扩展了吧,服务商自己应该开好了吧,谢谢。


一般情况下,服务商都是开启了的。

谢谢,我回去试后结贴,谢谢。

好像不行啊,我增加以后,页面什么都显示不了了。我还有几个疑问请教:
1、按照我的理解,逻辑是先判断缓存有无数据,如有则从缓存提取数据;如没有,则从数据库提取数据,并ECHO,然后 $memcache->set('results', $row);但是您的代码,我理解不了这个思路,没有if else,只有if。
2、如果我的页面中需要提取好几次数据,如$result = mysql_query...,还有$result1 = mysql_query...,是不是每次提取数据时都得加这些代码?还是一个页面,只要设置一次,然后get('results'),get('results1'),get('results2')就可以了?
3、$memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211); //memcache默认端口号是11211
这一句,我能加到IncDB.php(这是链接数据库设置的文件)中去,统一调用么?
谢谢指点。

能教教我么?谢谢啊。

这个。。。。。。。

大神们,有空稍微理一下我吧...

好像不行啊,我增加以后,页面什么都显示不了了。我还有几个疑问请教:
1、按照我的理解,逻辑是先判断缓存有无数据,如有则从缓存提取数据;如没有,则从数据库提取数据,并ECHO,然后 $memcache->set('results', $row);但是您的代码,我理解不了这个思路,没有if else,只有if。
2、如果我的页面中需要提取好几次数据,如$result = mysql_query...,还有$result1 = mysql_query...,是不是每次提取数据时都得加这些代码?还是一个页面,只要设置一次,然后get('results'),get('results1'),get('results2')就可以了?
3、$memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211); //memcache默认端口号是11211
这一句,我能加到IncDB.php(这是链接数据库设置的文件)中去,统一调用么?
谢谢指点。


1、我忘了写了   else{ $row = $memcache->get('results'); }
2、每次提取数据时都需要加这些代码先判断缓存。
3、不需要放到数据库配置里,memcache是缓存扩展,放在系统配置里就可以了。

哥 啊,是在代码的最后,加上else{ $row = $memcache->get('results'); }就可以了?系统配置是什么?我的就是这个页面,如果不把那些代码($memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211);)放在一个文件里调用,如IncDB.php,我每次都得再写啊。我没有专门的系统配置页面。

使用 memcache 需要安装 memcached 服务器和与 php 版本对应的 php_memcache 扩展

如果是全局使用,那么
$memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211);
只需写一次,当然可以写在嵌入文件中
但你并不能保证不会在函数里使用

其实你的核心问题还是我一开始就提出的:你如何知道内容发生的变化
如果你不解决这个问题,什么其他技术手段的是枉然的

哥 啊,是在代码的最后,加上else{ $row = $memcache->get('results'); }就可以了?系统配置是什么?我的就是这个页面,如果不把那些代码($memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211);)放在一个文件里调用,如IncDB.php,我每次都得再写啊。我没有专门的系统配置页面。


既然没有配置文件,那就放到IncDB.php里就好了。
<?phpinclude("IncDB.php"); session_start () ;//使用memcache对象$memcache = new Memcache;$memcache->connect('memcache主机地址', 11211); //memcache默认端口号是11211if(($row = $memcache->get('results')) == false){		//缓存里没有得到results,则去数据库查询	$result = mysql_query("SELECT * FROM userlinks where id='a02' and userid=‘".$_SESSION['id']."’ order by datetime desc", $link);	$row = mysql_fetch_row($result);	mysql_close($link); 	$memcache->set('results', $row); //查询数据库之后再放入缓存}echo "$row[1]"; echo"<br>"; echo "$row[2]";?>

使用 memcache 需要安装 memcached 服务器和与 php 版本对应的 php_memcache 扩展

如果是全局使用,那么
$memcache = new Memcache;
$memcache->connect('memcache主机地址', 11211);
只需写一次,当然可以写在嵌入文件中
但你并不能保证不会在函数里使用

其实你的核心问题还是我一开始就提出的:你如何知道内容发生的变化
如果你不解决这个问题,什么其他技术手段的是枉然的


是用户在EDIT页面,修改数据后,该内容才会发生变化。也就是说,我可以写在IncDB.php文件里调用就可以了?谢谢!

谢谢两位大神。。。我试试。

memcached 的内容是保存在内存中的,因此系统重启后,缓存的内容都会消失。
所以仅在修改的时候写缓存是不够的

那有办法么?我的初衷就是想提高网页响应速度,memcached能够实现么?

另外,如果我有1万个用户,那么在服务器上就得要存1万套数据?不知是否理解正确。我觉得能存在客户端最好,但不知怎么把一条条数据存在客户端并读取。

要做缓存,肯定要考虑更新数据的情况,比如你说的用户有可能修改资料。 你在程序里,就在用户修改资料后,把相应的缓存删掉就行了。

谢谢楼上的提示。
我崩溃了,就是不行,也没有报错。我是这么写的

include("IncDB.php"); 
session_start () ;
 $memcache = new Memcache;
$memcache->connect('localhost',11211) or die("链接失败!");
if(($row = $memcache->get('results')) == false){
 $result = mysql_query("SELECT * FROM userlinks where id='a02' and userid='".$_SESSION['id']."' order by datetime desc ", $link);
    $row = mysql_fetch_row($result);
 echo "$row[1]"; 
echo"
"; 
echo "$row[2]";
    $memcache->set('results', $row); 
 mysql_close($link);}
else{ $row = $memcache->get('results'); 
echo "$row[1]"; 
echo"
"; 
echo "$row[2]";}

?> 

谢谢楼上的提示。
我崩溃了,就是不行,也没有报错。我是这么写的

include("IncDB.php"); 
session_start () ;
 $memcache = new Memcache;
$memcache->connect('localhost',11211) or die("链接失败!");
if(($row = $memcache->get('results')) == false){
 $result = mysql_query("SELECT * FROM userlinks where id='a02' and userid='".$_SESSION['id']."' order by datetime desc ", $link);
    $row = mysql_fetch_row($result);
 echo "$row[1]"; 
echo"
"; 
echo "$row[2]";
    $memcache->set('results', $row); 
 mysql_close($link);}
else{ $row = $memcache->get('results'); 
echo "$row[1]"; 
echo"
"; 
echo "$row[2]";}

?> 


在程序的各个位置打印一下可能出错的变量,排错是个麻烦的过程。

这么晚还回了?感谢。弱弱的问,咋写啊。不要问我有多水~~~

这么晚还回了?感谢。弱弱的问,咋写啊。不要问我有多水~~~


用var_dump()来打印啊。。。话说,这个memcache缓存你完全可以自己找点资料,看看别人的博客去学习的。。。

这么问永远没个头,把里面提到的几个关键的内容去学习一下,然后在学习的时候遇到不明白的地方再来问效率会更好 不然下次你还是得问这些问题。

memcache
文件缓存

我其实是研究了几天之后,还是没搞明白才发帖求助的,可能是基础太差,也可能是智商不在家,反正没搞懂。

我写成这样,是不是就能打印错误了?

include("IncDB.php"); 
session_start () ;
 $memcache = new Memcache;
$memcache->connect('localhost',11211) or die("链接失败!");
if(($row = $memcache->get('results')) == false){
 $result = mysql_query("SELECT * FROM userlinks where id='a02' and userid='".$_SESSION['id']."' order by datetime desc ", $link);
    $row = mysql_fetch_row($result);
var_dump($row)
 echo "$row[1]"; 
echo"
"; 
echo "$row[2]";
    $memcache->set('results', $row); 
 mysql_close($link);}
else{ $row = $memcache->get('results'); 
echo "$row[1]"; 
echo"
"; 
echo "$row[2]";
var_dump($row)}

?> 

既然你是在调试程序,并多出打印点
那么你应该给出程序的运行结果吧?

xuzuning 好,我现在单位,没法把页面上传到空间,所有还不知道调试结果。另外,我那个多出打印点的代码对吗?
还有,我觉得您说的策略的确是问题,而且,我也觉得要是能把数据存到客户端是最好的。我的每个页面很简单,也很小,但内容都是从数据库里提取数据显示,而每个用户页面显示的内容,除了用户自己修改会立即有变化以外,其他一般变化不大(可能几个月才变一点)。因为每次从数据库提数慢,我就想如果能实现把每个用户的数据缓存在客户端,然后当其自己修改时再更新该缓存就可以了。不知道是否可以实现。另外,这些页面,当我在本地测试时很快,一上传空间就慢的没法用了。

再回PhpNewnew,我其实各种途径学习缓存有一个多礼拜,但确实没搞懂。我也知道老麻烦别人不好。放心,如果我还是没学会,我会及时结贴的。谢谢关心。



 你这个 用 memcache  是不行的。这个缓存技术用不了,你这个上面。

最好,缓存到服务器文件,注明一下时间。然后,用户每次改,也记录时间。时间不对上,就重新缓存。

这是概念。。

其实你现在的问题,是打开慢,这个暂时还不需要缓存的,你在数据表中,加索引,打开就很快了。

我看到这个帖子http://www.2cto.com/kf/201407/319353.html
上面好像就说了,可以在客户端存储读取数据。我不知道是否可行。

你先把概念弄清楚!本地是一个相对概念:
浏览器访问你的 php 网站,那么浏览器所在的机器就是本地
php 访问数据库服务器,那么 php 所在的机器就是本地
你给的那个连接中并没有说把数据缓存到了客户端(当然相对于数据库,php也是客户端)

如果你这的希望将页面缓存到客户的浏览器缓冲区去的话,只需要当客户再次访问时发个 304 头就可以了
当然你依然还是要知道数据是否发生了变化。于是问题又回到了原点: 你如何知道内容发生的变化
只有这个问题解决了,才有上技术手段的可能

用户在修改了内容以后就内容就发生变化了。我知道你有种对牛弹琴的感觉,但我确实low,也没办法。sorry
如果换个角度,我的原始需求就是希望不用每次访问数据库获得数据,来提高响应速度,您有什么建议?谢谢大神。

1. 先写一个memcache的简单实例,网上查下有很多,熟悉了之后,再应用到自己的代码中。

2. 提一点,memcache有一个过期时间的,设置了过期时间,就不用担心数据存到里面会越来越大了。

3. 大致思路,
a. 每次更新数据,更新之后,去memcached检查,如果存在,则更新memcached;如果不存在,则不做动作。
b. 每次访问数据,先去memcahced检查,如果存在则直接取出使用;如果不存在则从数据库获取,并存于memcached。

4. memcached有个小缺点,数据类型单一,且不会将数据写入硬盘。如果有这方面的需求,建议看看redis。redis还有主从备份。
redis用法请参照第1-3点,将memcached都改成redis。

还是没学会,我放弃了!谢谢各位大神。。。。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn