Lumen中使用速度更快的PhpRedis擴展(更新隊列驅動)

歡迎關注個人博客 http://targetliu.comphp

Lumen的確是一款適合作API,速度很快的框架。可是在項目中使用Redis時發現Lumen默認使用的 predis/predis 會拖慢總體速度,特別是在高併發的狀況下,因此尋思着使用 PhpRedis 代替,畢竟 PhpRedis 是C語言寫的模塊,性能上確定優於 predislaravel

文中例子已經整理成一個 composer 包,文末有簡單介紹。git

[TargetLiu/PHPRedis]github

編譯安裝PhpRedis

因爲 PhpRedis 是C語言寫的模塊,須要編譯安裝。安裝方法網上一搜一大把,請根據本身的環境選擇相應的方法安裝便可。併發

兩個可能用得上的連接:app

Lumen中使用PhpRedis

很簡單,只須要在 bootstrap/app.php 中添加下列代碼將PhpRedis注入容器便可:

$app->singleton('phpredis', function(){
    $redis = new Redis;
    $redis->pconnect('127.0.0.1'); //創建鏈接
        $redis->select(1); //選擇庫
        $redis->auth('xxxx'); //認證
    return $redis;
});
unset($app->availableBindings['redis']);

綁定後便可經過 app('phpredis') 直接使用 PhpRedis 了,具體使用方法能夠看相應的官方文檔。

Lumen中爲PhpRedis增長Cache驅動

因爲實際使用中更多的將Redis用於緩存,Lumen自帶的Redis緩存驅動是基於 predis/predis 實現,咱們如今新建一個驅動以支持 Phpredis

新增Cache驅動詳細方法能夠查看 官方文檔,這裏指羅列一些關鍵的點。更多的內容也能夠查看 TargetLiu/PHPRedis

咱們首先建立一個 ServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
use TargetLiu\PHPRedis\PHPRedisStore;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('phpredis', function ($app) {
            return Cache::repository(new PHPRedisStore($app->make('phpredis'), $app->config['cache.prefix']));
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

這樣就創建一個名爲 phpreids 的驅動。再建立一個基於 Illuminate\Contracts\Cache\Store 契約的緩存操做類用以操做 PhpRedis

<?php

namespace TargetLiu\PHPRedis;

use Illuminate\Contracts\Cache\Store;

class PHPRedisStore implements Store
{

    /**
     * The Redis database connection.
     *
     * @var \Illuminate\Redis\Database
     */
    protected $redis;

    /**
     * A string that should be prepended to keys.
     *
     * @var string
     */
    protected $prefix;

    /**
     * Create a new Redis store.
     *
     * @param  \Illuminate\Redis\Database  $redis
     * @param  string  $prefix
     * @return void
     */
    public function __construct($redis, $prefix = '')
    {
        $this->redis = $redis;
        $this->setPrefix($prefix);
    }

    /**
     * Retrieve an item from the cache by key.
     *
     * @param  string|array  $key
     * @return mixed
     */
    public function get($key)
    {
        if (!is_null($value = $this->connection()->get($this->prefix . $key))) {
            return is_numeric($value) ? $value : unserialize($value);
        }
    }

    /**
     * Retrieve multiple items from the cache by key.
     *
     * Items not found in the cache will have a null value.
     *
     * @param  array  $keys
     * @return array
     */
    public function many(array $keys)
    {
        $return = [];

        $prefixedKeys = array_map(function ($key) {
            return $this->prefix . $key;
        }, $keys);

        $values = $this->connection()->mGet($prefixedKeys);

        foreach ($values as $index => $value) {
            $return[$keys[$index]] = is_numeric($value) ? $value : unserialize($value);
        }

        return $return;
    }

    /**
     * Store an item in the cache for a given number of minutes.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @param  int     $minutes
     * @return void
     */
    public function put($key, $value, $minutes)
    {
        $value = is_numeric($value) ? $value : serialize($value);

        $this->connection()->set($this->prefix . $key, $value, (int) max(1, $minutes * 60));
    }

    /**
     * Store multiple items in the cache for a given number of minutes.
     *
     * @param  array  $values
     * @param  int  $minutes
     * @return void
     */
    public function putMany(array $values, $minutes)
    {
        foreach ($values as $key => $value) {
            $this->put($key, $value, $minutes);
        }
    }

    /**
     * Increment the value of an item in the cache.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @return int|bool
     */
    public function increment($key, $value = 1)
    {
        return $this->connection()->incrBy($this->prefix . $key, $value);
    }

    /**
     * Decrement the value of an item in the cache.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @return int|bool
     */
    public function decrement($key, $value = 1)
    {
        return $this->connection()->decrBy($this->prefix . $key, $value);
    }

    /**
     * Store an item in the cache indefinitely.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @return void
     */
    public function forever($key, $value)
    {
        $value = is_numeric($value) ? $value : serialize($value);

        $this->connection()->set($this->prefix . $key, $value);
    }

    /**
     * Remove an item from the cache.
     *
     * @param  string  $key
     * @return bool
     */
    public function forget($key)
    {
        return (bool) $this->connection()->delete($this->prefix . $key);
    }

    /**
     * Remove all items from the cache.
     *
     * @return void
     */
    public function flush()
    {
        $this->connection()->flushDb();
    }

    /**
     * Get the Redis connection instance.
     *
     * @return \Predis\ClientInterface
     */
    public function connection()
    {
        return $this->redis;
    }

    /**
     * Get the Redis database instance.
     *
     * @return \Illuminate\Redis\Database
     */
    public function getRedis()
    {
        return $this->redis;
    }

    /**
     * Get the cache key prefix.
     *
     * @return string
     */
    public function getPrefix()
    {
        return $this->prefix;
    }

    /**
     * Set the cache key prefix.
     *
     * @param  string  $prefix
     * @return void
     */
    public function setPrefix($prefix)
    {
        $this->prefix = !empty($prefix) ? $prefix . ':' : '';
    }
}

經過以上兩個步驟基本上就完成了Cache驅動的建立,如今只須要在 bootstrap/app.php 中注入新建的Cache驅動而後配置 .envCACHE_DRIVER = phpredis ,最後再在 config/cache.php 中加入相應的驅動代碼便可

'phpredis' => [
    'driver' => 'phpredis'
],

Cache的使用請查看Lumen官方文檔

一個基於PhpRedis的Lumen擴展包

[TargetLiu/PHPRedis]

安裝:composer require targetliu/phpredis

安裝及使用方法請看 README

這個包只是我作的一個簡單示例,引入了 PhpRedis 並作了最簡單的緩存驅動。目前支持根據 .env 獲取Redis配置、Cache的基本讀寫等。

Session和Queue能夠繼續使用Lumen自帶的Redis驅動,二者互不影響。下一步若有須要能夠繼續完善這兩部分的驅動。

這個包將根據本身工做需求以及你們的已經進一步完善。

歡迎你們提出意見共同完善。

相關文章
相關標籤/搜索