亲宝软件园·资讯

展开

使用php数据缓存技术提高执行效率

人气:0

为什么要使用php缓存技术?理由很简单:提高效率。在程序开发中,获取信息的方式主要是查询数据库,除此以外,也可能是通过Web Services或者别的某种方法,无论哪种方法,在大量的并发访问面前,它们都可能成为效率的瓶颈,为了解决这些问题,人们提出了很多解决方案,其中一些是利用优化软件(如:APC,Eaccelerator,Zend Optimizer等等)来提高程序的运行效率,合理的运用这些软件,往往能使程序的运行效率得到数量级上的提升,但前提是你必须拥主机的控制权,以便能够安装这些软件,如果你使用的是虚拟主机的话,那么只能祈祷你的服务提供商已经预装了某个优化软件,否则就必须自己使用PHP来实现相应的缓存功能。

PHP缓存技术是一种解释型语言,属于边编译边运行,包括PHP编译缓存和PHP数据缓存两种。PHP缓存,这种运行模式的优点是程序修改很方便,但是运行效率却很低下。PHP编译缓存针对这种情况做改进处理,使得PHP语言只要运行一次,就可以把程序的编译结果缓存起来。这样,接下来的每次运行都不需要再次编译了,这大大提高PHP运行速度。

PHP 缓存介绍

什么是缓存

    数据交换的缓冲区(称作Cache)
    临时文件交换区

缓存作用

    减少网络延迟,加快页面打开速度
    减少数据查询次数,降低数据库压力
    降低系统负荷,极大的提升系统性能

常用缓存类型

    文件缓存:使用 PHP 文件操作函数,把数据缓存到服务器磁盘文件中
    内存缓存:Redis、Memcached、MongoDB
    Opcode缓存:PHP 是一种解释型脚本语言,在 PHP 执行过程中,虚拟机会把 PHP 代码翻译成中间语言,这种中间语言就叫 Opcode,然后虚拟机再把 Opcode 顺序执行。把 PHP 代码对应的 Opcode缓存到内存中,加速 PHP 执行,减少了代码翻译成中间语言这一步操作。

文件缓存内存缓存Opcode缓存
存储介质磁盘文件内存内存
不足IO操作慢、文件锁的存在占内存、不持久部署代码刷新慢
应用举例新闻数据、城市区域会员、商品、SessionOpcodeCache(代码加速)

PHP 常用内存缓存介绍

    PHP是一种脚本语言,脚本执行结束之后,所有的变量全部释放掉,本身没有能力将数据常驻内存。
    PHP借助于内存服务器将缓存数据储存在服务器内存。
    优点:读写速度快、跨服务器存储(例如在做多服务器集群的时候,可以将 Session 存储于内存缓存服务器中)、易于解决主从同步问题,并发问题。
    不足:占用了内存空间、缓存数据有大小限制、数据不易持久化存储。(但是内存缓存带给我们的方便足够可以忽略他的不足)
    常用内存缓存:Memcached、Redis、MongoDB

MemcachedRedisMongoDB
储存数据类型stringstring, list, hash, setbson 丰富查询方式
数据储存位置内存内存 + 硬盘内存 + 硬盘
持久化最长30天RDB 文件快照,AOF(记录写操作)持久化journal持久化
使用场景Session 商品缓存(缓存 < 1MB)缓存、队列日志、区域信息、评论

php opcode缓存

PHP Opcode原理

Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码

<?php
   echo "Hello World";
   $a = 1 + 1;
   echo $a;
?>

PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)

1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2.Parsing, 将Tokens转换成简单而有意义的表达式
3.Compilation, 将表达式编译成Opocdes
4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。

 学过编译原理的同学都应该对编译原理中的词法分析步骤有所了解,Lex就是一个词法分析的依据表。 Zend/zend_language_scanner.c会根据Zend/zend_language_scanner.l(Lex文件),来输入的 PHP代码进行词法分析,从而得到一个一个的“词”,PHP4.2开始提供了一个函数叫token_get_all,这个函数就可以讲一段PHP代码 Scanning成Tokens;如果用这个函数处理前面的PHP代码,将会得到如下结果:

Array
(
    [0] => Array
        (
           [0] => 367
           [1] => Array
        (
            [0] => 316
            [1] => echo
        )
    [2] => Array
        (
            [0] => 370
            [1] =>
        )
    [3] => Array
        (
            [0] => 315
            [1] => "Hello World"
        )
    [4] => ;
    [5] => Array
        (
            [0] => 370
            [1] =>
        )
    [6] => =
    [7] => Array
        (
            [0] => 370
            [1] =>
        )
    [8] => Array
        (
            [0] => 305
            [1] => 1
        )
    [9] => Array
        (
            [0] => 370
            [1] =>
        )
    [10] => +
    [11] => Array
        (
            [0] => 370
            [1] =>
        )
    [12] => Array
        (
            [0] => 305
            [1] => 1
        )
    [13] => ;
    [14] => Array
        (
            [0] => 370
            [1] =>
        )
    [15] => Array
        (
            [0] => 316
            [1] => echo
        )
    [16] => Array
        (
            [0] => 370
            [1] =>
        )
    [17] => ;
)

分析这个返回结果我们可以发现,源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。而,其他的比如标签,操作符,语句,都会被转换成一个包含俩部分的Array: Token ID (也就是在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING),和源码中的原来的内容。
  接下来,就是Parsing阶段了,Parsing首先会丢弃Tokens Array中的多于的空格,然后将剩余的Tokens转换成一个一个的简单的表达式

1.echo a constant string
2.add two numbers together
3.store the result of the prior expression to a variable
4.echo a variable

  然后就改Compilation阶段了,它会把Tokens编译成一个个op_array, 每个op_arrayd包含如下5个部分:

1.Opcode数字的标识,指明了每个op_array的操作类型,比如add , echo
2.结果 存放Opcode结果
3.操作数1 给Opcode的操作数
4.操作数2
5.扩展值1个整形用来区别被重载的操作符

  比如,我们的PHP代码会被Parsing成:

* ZEND_ECHO 'Hello World'
* ZEND_ADD ~0 1 1
* ZEND_ASSIGN !0 ~0
* ZEND_ECHO !0

 php文件缓存

因为如果程序访问数据库时数据量较大,执行起来会比较慢。而且每一次刷新页面都会访问依稀数据库,然后再把数据显示在页面上。 设置缓存也有一个缺点,那就是缓存时间要设置好,如果缓存时间较长,那么数据库数据变化时,不能及时的在页面上显示。例如缓存不能用在秒杀商品,或者出售商品上面,因为数量不能及时的更新。

<?php
//缓存文件一般都放在caches文件夹里面。

//定义一个该页面的缓存文件路径,也就是该缓存的文件放在哪个文件夹里面。

$filename = "../cache/testhuancun.html";//定义了一个缓存的文件,文件名为testhuancun.html,位置在../cache文件夹里面。

//设置一个缓存时间
$time = 10;//代表缓存时间设置为10s.

//判断缓存文件是否存在
if(!file_exists($filename) || filemtime($filename)+$time<time())
//判断文件是否存在,如果不存在,执行{}里面的代码。还要判断缓存时间有没有过,如果已经过了,要重新读取数据库更新缓存。
//filemtime($filename)读取文件最后被修改的时间,time()取当前时间戳

{
    //开启内存缓存
    ob_start();//这里开启内存缓存以后,下面要输出的内容全部放在内存缓存里面。

    include("../init.inc.php");
    include("../DBDA.php");
    $db = new DBDA();
    $sql = "select * from nation";
    $attr = $db->Query($sql);
    $smarty->assign("nation",$attr);
    $smarty->display("test.html");

    //把内存里面的内容读出来
    $nr = ob_get_contents();//ob就是代表的缓存,读取的内容就是整个静态页面。

    //将读到的内容存放到缓存文件
    file_put_contents($filename,$nr);//get是取出内容,put是往里放内容,把内存缓存的文件存到¥filename里面。


    //清除内存缓存
    ob_flush();//把内存缓存的内容清除掉,不让它们继续留在缓存内存里面,但是需要缓存的内容已经放在了$filename里面了,已经保存下来了。

    echo "#############################";//输出内容加上一句话,观察输出内容是输出的缓存页面还是加载数据库的页面。这句话放在了ob_flush后面,不会被清除掉。
}
else//如果缓存文件存在,直接将缓存文件拿到页面显示。
{
    include($filename);//将缓存的页面加载到显示页面中
}

加载全部内容

相关教程
猜你喜欢
用户评论