讓laravel的cache支援用connection選擇redis服務

來源:互聯網
上載者:User

先看下我的database.php中關於redis的配置:

 代碼如下 複製代碼
 /*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => array(
 'cluster' => false,
 'default' => array(
  'host'     => '192.168.1.120',
  'port'     => 6379,
  'database' => 0,
 ),
 'cache' => array(
  'host'     => '192.168.1.120',
  'port'     => 6379,
  'database' => 1,
 ),
 'session' => array(
  'host'     => '192.168.1.120',
  'port'     => 6379,
  'database' => 2,
 ),
),

我這麼配置的意圖就是想在緩衝的時候使用cache這個配置項,session的資料存放區在session這個配置項。
那麼我們先來看下我在app/config/cache.php中的相關配置
 

 代碼如下 複製代碼
'driver' => 'redis',
   //.......
  'path' => storage_path().'/cache',
/*
|--------------------------------------------------------------------------
| Database Cache Connection
|--------------------------------------------------------------------------
|
| When using the "database" cache driver you may specify the connection
| that should be used to store the cached items. When this option is
| null the default database connection will be utilized for cache.
|
*/
'connection' => 'cache',

然後再來看下我在app/config/session.php中的相關配置
 

 代碼如下 複製代碼
  'driver' => 'redis',
   //.......
   'files' => storage_path().'/sessions',
/*
|--------------------------------------------------------------------------
| Session Database Connection
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the database
| connection that should be used to manage your sessions. This should
| correspond to a connection in your "database" configuration file.
|
*/
'connection' => 'session',

這裡我把兩者的驅動都設定為redis。
經過對以上的設定進行測試,發現一個問題:session的資料可以正常儲存到指定的服務中,而cache的資料並沒有按照預期的進行了儲存,而是儲存在了session的服務中。這是為什麼呢?請繼續往下看。
現在我們換種方法,我們稍微修改下上面的配置,我們把session的驅動改成非redis,比如memcache等,這時我們再進行測試,效果如下:
緩衝的資料存放區到了default上面,並非我們期望的cache服務。這又是為什麼呢?
通過上面我們發現了兩個問題,暫且按順序叫問題A和問題B吧。
這裡我們先來解決問題B。
問題B的產生原因是laravel的cache並不支援redis的connection(也就是說當緩衝的驅動是redis時,connection的設定沒有意義的),只有database驅動時才支援,那麼我們怎麼改,才能支援呢?,修改起來很簡單。
既然是cache那麼肯定找cacheManager了: Laravel/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php
修改一下方法的代碼為一下:
 

 代碼如下 複製代碼
  /**
 * Create an instance of the Redis cache driver.
 *
 * @return IlluminateCacheRedisStore
 */
protected function createRedisDriver()
{
 $redis = $this->app['redis'];
 // 增加一行擷取cache connection值的代碼
 $connection = $this->app['config']['cache.connection'];
 // 為RedisStore設定第三個參數
 return $this->repository(new RedisStore($redis, $this->getPrefix(), $connection));
}

OK,改完了,是不是很簡單呢。
這樣子一改,就能解決我們的問題B,可以保證當我們的cache的驅動為redis時,緩衝的資料是存在connection(cache)指定的服務中的。
那麼我們這樣子改了之後能否解決A問題呢?很抱歉,不能!!!
那按照醬紫我測試了下,結果還是跟上面沒改之前的結果一樣(session的資料可以正常儲存到指定的服務中,而cache的資料並沒有按照預期的進行了儲存,而是儲存在了session的服務中。)
目前我還沒有發現有好的解決方案,為什麼,請看下面分析。
其實我們大家都知道,session其實也一種緩衝,那麼既然是一種緩衝,那麼肯定是按照緩衝的流程來處理的(其實laravel的部分session驅動(redis,memcache,memcached)走的就是緩衝的儲存流程)
具體來看代碼:
檔案是:Laravel/vendor/laravel/framework/src/Illuminate/Session/SessionManager.php
 

 代碼如下 複製代碼
  /**
 * Create an instance of the Redis session driver.
 *
 * @return IlluminateSessionStore
 */
protected function createRedisDriver()
{
               // 這裡會設定當前redis的connection為cache
 $handler = $this->createCacheHandler('redis');
               // 這裡會設定當前redis的connection為session(也就是說覆蓋了上面的)
 $handler->getCache()->getStore()->setConnection($this->app['config']['session.connection']);
 return $this->buildSession($handler);
}

這段代碼是在應用啟動的時候通過booting callbacks啟動session時調用的一個方法,這個方法的功能是建立一個redis的session驅動。
我們不妨看下createCacheHandler這個方法:

 代碼如下 複製代碼
   /**
 * Create the cache based session handler instance.
 *
 * @param  string  $driver
 * @return IlluminateSessionCacheBasedSessionHandler
 */
protected function createCacheHandler($driver)
{
 $minutes = $this->app['config']['session.lifetime'];
               // 這裡最終會調用下面的CacheManager的createRedisDriver方法
 return new CacheBasedSessionHandler($this->app['cache']->driver($driver), $minutes);
}

我們來看下CacheManager的createRedisDriver方法
檔案是: Laravel/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php
 

 代碼如下 複製代碼
  /**
 * Create an instance of the Redis cache driver.
 *
 * @return IlluminateCacheRedisStore
 */
protected function createRedisDriver()
{
 $redis = $this->app['redis'];
 
 $connection = $this->app['config']['cache.connection'];
 // 這裡我們設定我們cache的redis connection
 return $this->repository(new RedisStore($redis, $this->getPrefix(), $connection));
}

這段代碼是我們改過之後的代碼,但是沒關係。通過上面的分析,我們發現,其實在cache和session同時使用一個驅動的時候最終的驅動是由session的設定檔中的connection值決定的,因為它覆蓋了cache設定的驅動值。那麼造成這個問題的原因就是我們上面說的,session的所有資料處理是根據cache的流程處理的,因為session也是一種cache。=.=
其實這個要說是個問題,其實也是個問題,因為它沒有按照我們的要求進行處理。
要是不是個問題,其實也不是個問題,因為session從某種意義上來說也是緩衝,當然後面設定的覆蓋了前面設定的。
那麼有沒有辦法解決呢?提供兩個側面的解決方案:
1:兩者不要同時使用一種驅動,可以交替者。比如cache用memcache,session用redis等。
2:就是用上次我提到的方案:

 代碼如下 複製代碼

$redisCache = App::make('cache'); // Assumes "redis" set as your cache
$redisCache->setConnection('cache'); // Your redis cache connection
$redisCache->put('testtCacheIndex', 'fbbinValue', 10000);

// 或者

$redis = Redis::connection('cache');
$redis->set('fbbin', 'fbbinValue');
var_dump($redis->get('fbbin'))

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.