PHP cache应用

来源:互联网 发布:海知智能 王宇 编辑:程序博客网 时间:2024/06/12 01:01

PHP cache应用

作者:Wucl

时间:2014-12-08

章节内容:基础背景、实际应用、个人心得(这个人非常没品德,想到什么就写什么。)。

1. 基础背景:

在我们的网站项目中综合性页面的业务逻辑渐渐健全,随之数据接口也日渐增加,举个例子:综合性首页的数据接口已达到87个。然而,获取中间件接口数据是经过http协议,每个接口访问时间在20ms左右。为解决数据访问时间过长的问题项目组决定引入缓存的概念。

2. 实际应用:

1) PHP项目中常见的缓存有memcacheredis,下面的内容围绕redis展开(两者的APIhttp://my.oschina.net/cniiliuqi/blog/67423 ; http://php.net/manual/zh/book.memcache.php)。

2) 连接缓存服务器:由于连接次数频繁,我们选择使用了持久化连接方式,并把连接存放于静态变量。

获得一个cache连接:

/**

     * 获得一个cache连接 

     * @param string $actionType

     */

    public function _getConn() {

        // 处理连接信息

        $cacheConn = null;

        switch ($this->_cacheType) {

            case "memcached" :

             if(!empty(static::$memInstance['memcached'] ) && static::$memInstance['memcached'instanceof Memcached) {

             $cacheConn = static::$memInstance['memcached'];

             }else{

             $cacheConn = $this->memcachedConn();

             static::$memInstance['memcached'] = $cacheConn;

             }

                break;

            case "redis" :

             if(!empty(static::$memInstance['redis'] ) && static::$memInstance['redis'instanceof Redis) {

             $cacheConn = static::$memInstance['redis'];

             try{

             $cacheConn->ping(); //如果链接关闭则重新连

             }catch(\RedisException $e){

             $cacheConn = $this->redisConn();

             static::$memInstance['redis'] = $cacheConn;

             }

             }else{

             $cacheConn = $this->redisConn();

             static::$memInstance['redis'] = $cacheConn;

             }

                break;

        }

        return $cacheConn;

    }

redis服务器连接:

/**

     * redis服务器连接

     * @return Ambigous <NULL, \Redis>

     */

    private function redisConn(){

     $cacheConn = null;

     $tryI = 0;

     while ( $cacheConn == null && $tryI < 10 ) {

     try {

     $cacheConn = new Redis ();

     $serverSetting = Config::$redis;

     if (! $cacheConn->pconnect ( $serverSetting[$this->_serverType]['ip'],  $serverSetting[$this->_serverType]['port'])) {

     $this->_serverType = "default";

     $cacheConn->pconnect (  $serverSetting[$this->_serverType]['ip'],  $serverSetting[$this->_serverType]['port']);

     }

     $cacheConn->setOption ( Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE );

     // 选择DB

     $redisDB = $serverSetting[$this->_serverType]['redisDb'];

     if ($redisDB > 0 && $redisDB <= 16) {

     $cacheConn->select ( $redisDB );

     } else {

     $cacheConn->select ( 0 );

     }

     } catch ( \Exception $e ) {

     sleep ( $tryI * 0.3 );

     $tryI ++;

     $cacheConn = null;

     }

     }

     return $cacheConn;

  }

memcached服务器连接

/**

     * memcached服务器连接

     * @return multitype:

     */

    private function memcachedConn(){

     $cacheConn = null;

     $tryI = 0;

     while ( $cacheConn == null && $tryI < 10 ) {

     try {

     $cacheConn = new Memcached ();

     $serverSetting = Config::$memcached;

     if (is_array ( $serverSetting [$this->_serverType] )) {

     foreach ( $serverSetting [$this->_serverTypeas $vals ) {

     $cacheConn->addServer ( $vals['ip'],  $vals['port']);

     }

     }

     if (! empty ( $cacheConn )) {

     $cacheConn->setOption ( Memcached::OPT_CONNECT_TIMEOUT, 3000 );

     $cacheConn->setOption ( Memcached::OPT_RECV_TIMEOUT, 3000 );

     $cacheConn->setOption ( Memcached::OPT_SEND_TIMEOUT, 3000 );

     $cacheConn->setOption ( Memcached::OPT_SERVER_FAILURE_LIMIT, 3 );

     }

     } catch ( \Exception $e ) {

     sleep ( $tryI * 0.3 );

     $tryI ++;

     $cacheConn = null;

     }

     }

     return $cacheConn;

}

配置文件结构:

static $redis = array(

        'default' => array(

            'ip' => '***',

            'port' => ***,

            'redisDb' => ***

        ),

        'db0' => array(

            'ip' => '***',

            'port' => ***,

            'redisDb' => ***

        ),

        'db2' => array(

            'ip' => '***',

            'port' => ***,

            'redisDb' => ***

        )

    );

3)获取和设置值注意序列化和压缩以及缓存时间:

/**

     * 取得缓存

     * @param $key 缓存关键词

     * @param $compress 是否要解压缩

     */

    public function get($key, $compress = true) {

        $conn = $this->_getConn ();

        if (empty ( $conn )) {

            return false;

        }

        $result = false;

        try {

            if (! empty ( $conn )) {

                if ($this->_cacheType == "memcached") {

                    $conn->setOption ( Memcached::OPT_COMPRESSIONfalse );

                }

                $result = $conn->get ( $key );

                if ($this->_cacheType == 'redis') {

                    //$conn->close ();

                    unset ( $conn );

                }

            }

        } catch ( \Exception $e ) {

        }

        if ($result !== false && $compress) {

            $result = FormatClass::unserialize ( $result, $compress );

        }

        return $result;

    }

/**

     * 设置缓存

     *

     * @param $key

     * @param $content

     * @param $expire

     * @param $compress

     */

    public function set($key, $content, $expire = -1, $compress = true) {

        $conn = $this->_getConn ();

        if (empty ( $conn )) {

            return false;

        }

        if ($compress) {

            $data = FormatClass::serialize ( $content, $compress );

        } else {

            $data = $content;

        }

        try {

            // 一定要有过期时间。避免缓存有增无减

            if ($expire < 0) {

                $expire = 86400;

            }

            switch ($this->_cacheType) {

                case "memcached" :

                    $conn->setOption ( Memcached::OPT_COMPRESSIONfalse );

                    $result = $conn->set ( $key, $data, $expire );

                    break;

                case "redis" :

                    $result = $conn->setex ( $key, $expire, $data );

                    break;

            }

            if ($this->_cacheType == 'redis') {

                $conn->close ();

                //unset ( $conn );

            }

        } catch ( \Exception $e ) {

            error_log ( 'Cache set error' );

        }

        return $result;

    }

}

4)删除和清空缓存不多做介绍。

3. 个人心得:

刚开始我们的缓存机制是使用普通链接,在上线时出现由于链接数剧增而导致服务器奔溃的问题。改用持久化连接并做了单例之后,这种情况大为改善。

0 0