lumen 缓存

配置

 laravel 为后端缓存提供了丰富而统一的API,其配置信息位于 confing/cache.php文件中。在该文件中你可以指定应用默认使用哪个缓存驱动。laravel支持当前流行的后端缓存,例如memcached和redis

缓存配置文件还包含各种其他选项,这些选项都记录在文件中。对于较大型应用,建议使用更强大的驱动程序,例如memcached或redis.你甚至可以为同一驱动程序配置多个缓存配置

驱动得前提条件

Redis 

在使用laravel得redis缓存之前,你需要通过PECL安装phpRedis php扩展,或者通过Composer 安装predis/predis 包

缓存得使用

获取缓存实例

Illuminate\Contracts\Cache\Factory 和 Illuminate\Contracts\Cache\Repository 契约提供了laravel缓存服务得访问机制.Factory契约为你得应用程序定义了访问所有缓存驱动得机制。Repository契约通常是由你得cache配置文件指定的默认缓存通常是由你的cache 配置文件指定的默认缓存驱动实现的。

当然,你也可以使用Cache Facade ,我们将在后续的文档中介绍。Cache Facade 为Laravel 缓存契约底层的实现提供了方便又简洁的方法:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
/**
* 展示应用的所有用户列表
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');

//
}
}

访问多个缓存存储

使用Cache Facade,你可以通过store 方法来访问各种缓存存储。传入 store 方法的键应该对应cache 配置信息文件中的store配置数组中的store配置数组中所列的一个:

$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar',"baz",600);//10分钟

从缓存中获取数据

Cache Facade的 get 方法 用缓存中获取数据。如果该数据在缓存中不存在,那么该方法将返回null。正如你想的那样,你也可以向get 方法传递第二个参数,用来指定如果查找的数据不存在时你希望返回的默认值:

$value = Cache::get('key');

$value = Cache::get('key','default');

你甚至可以传递一个Closure 作位默认值。如果指定的数据在缓存中不存在,将返回 Closure的结果。传递闭包的方法允许你从数据库或其他外部服务中获取默认值

$value = Cache::get('key',function(){

    return  DB::table(...)->get();

}) 

检查缓存项是否存在

has  方法可以用于判断缓存项是否存在。如果值为null,则该方法将会返回false:

if(Cache::has('key')){

}

递增和递减值

increment和decrement方法可以用来调整缓存中整数项的值。这两个方法都可以传入第二个可选参数,这个参数用来指明要递增或递减的数量:

Cache::increment('key');

Cache::increment("key",$amout);

Cache::decrement("key");

Cache::decrement("key",$amount);

获取和存储

有时你可能想从缓存中获取一个数据,而当请求的缓存项不存在时,程序能为你存储一个默认值。例如你可能想从缓存中获取所有用户,当缓存中不存在这些用户时,程序将从数据库将这些用户取出并放入缓存。你可以使用Cache::remember方法实现:

$value = Cache::remember('users',$seconds,function(){

          return DB::table('users')->get();

})

如果缓存中不存在你想要的数据时,则传递给remember方法的 闭包 将被执行,然后将其结果返回并放置到缓存中。

你可以使用rememberForever 方法从缓存中获取数据或者永久存储它:

$vaue = Cache::rememberForever('users',function(){

           return DB::table('users')->get();

});

获取和删除

如果你需要从缓存中获取到数据之后再删除它,你可以使用pull方法。和get方法一样,如果缓存不存在,则返回null

$value = Cache::pull('key');

在缓存中存储数据

你可以使用Cache Facade的put方法将数据存储到缓存中:

Cache::put('key',$value,$seconds);

除了以整数形式传递过期时间的秒数,你还可以传递一个DateTime实例来表示该数据的到期时间

Cache::put('key' , 'value', now->addMinutes(10));

只存储没有的数据

add方法将只存储缓存中不存在的数据。如果存储成功,将返回true,否则返回false:

Cache::add('key','value',$seconds);

数据永久存储

forever 方法可用于持久化将数据存储到缓存中。因为这些数据不会过期,所以必须通过forget方法从缓存中手动删除它们:Cache::forever('key' , "value");

提示:如果你使用Memcached驱动,当缓存数据达到存储上限时,【永久存储】的数据可能会被删除

从缓存中删除数据

你可以使用forget 方法从缓存中删除这些数据

Cache::forget('key');

你也可以通过提供零或者负的TTL值来删除这些数据:

Cache::put('key','value',0);

Cache::put("key","value",-5);

你可以使用flush方法清空所有的缓存

Cache::flush();

注意:清空缓存的方法并不会考虑缓存前缀,会将缓存中的所有内容删除。因此在清除与其他应用程序共享的缓存时,请慎重考虑。

原子锁

注意:要想使用该特性,你的应用必须使用 memcached,dymodb或redis缓存驱动作为你应用的默认缓存驱动。此外,所有服务器必须与同一中央服务器进行通信。

原子锁允许对分布式锁进行操作而不必担心竞争条件。例如,laravel Forge使用原子锁来确保在一台服务器上每次只有一个远程任务在执行。你可以使用Cache::lock 方法来创建和管理锁:

use Illuminate\Support\Facades\Cache;

$lock = Cache::lock('foo' ,10);

if($lock->get()){

  $lock->release();

}

get 方法也可以接收一个闭包。在闭包执行之后,laravel 将会自动释放锁:

Cache::lock('foo')->get(function(){

   //获取无限期锁并自动释放

})

如果你在请求时锁无法使用,你可以控制laravel 等待指定的秒数。如果在指定的时间限制内无法获取锁,则会抛出Illuminate\Contracts\Cache\LockTimeoutException:

use Illuminate\Contracts\Cache\LockTimeoutException;

$lock = Cache::lock('foo',10);

try{

     $lock->block(5);

}catch(LockTimeoutException $e){

    //无法获取锁

}finally{

      optional($lock)->release();

}

 

Cache::lock('foo',10)->block(5,function(){

 //等待最多5秒后获取的锁

})

管理跨进程锁

 有时候,你可能希望在一个进程重获取锁然后在另一个进程中释放它。例如,你可能在一个web请求中获取锁 并且希望在由该请求出发的队列结束时释放锁。对于这样的场景,你应该把传递锁的作用域[owner token] 传递给队列任务,使队列任务可以使用给定的token 重新实例化锁:

//控制器里面

$podcast = Podcast::find($id);

$lock = Cache::lock('foo',120);

if($result = $lock->get()){

     ProcessPodcast::dispatch($podcast,$lock->owner())

}

//processPodcast Job 里面

Cache:restoreLock('foo',$this->owner)->release();

如果你想在无视当前锁的所有者情况下释放锁,你可以使用forceRelease 方法

Cache::lock('foo')->forceRelease();

Cache 辅助函数

除了可以使用Cache的门面以及Cache契约外,你也可以使用全局辅助函数Cache来获取和保存缓存数据。当只使用一个字符串参数调用 Cache 函数时,这将返回给定键对应的值。

$value = Cache('key');

如果你向函数提供了一组带有过期时间的键值对,那么在这段时间,它将缓存此数据。

cache(['key'=>'calue'] , $seconds);

cache(['key=>'value'] ,now()->addMinutes(10));

当Cache函数在没有任何参数的情况下被调用,那么它返回的将是一个实现Illuminate\Contracts\Cache\Factory的实例,并且允许你掉用其他的缓存方法:

cache()->remember('users',$seconds,function(){

           return DB::table('users')->get();

})

tip:如果在测试中使用全局函数Cache,你可以使用Cache::shouldReceive 方法就像测试Facade

 缓存标记

{注意} 当使用【file】或者database缓存驱动时,缓存标记将不支持。此外,当使用带有【永久】存储得缓存得多个缓存标记时,类似Memcached得缓存驱动性能最佳,他会自动清除旧得数据。

存储被打上标签得缓存数据

缓存标签允许你给相关得缓存标签项打上同一个标签以便后续可以清除这些缓存值。你可以通过传入一个被排序得标签数组来访问这些缓存项。例如,我们可以在使用标签得同时使用put方法来设置缓存。

Cache::tags(['people'  , 'artists' ])->put('John' , $john ,$second);

Cache::tage([ 'people' , ' authors' ])->put('Anne', $anne ,$second);

访问被打上标签得缓存数据,将相同标签得有序数组传递给 tags 方法,然后调用 get 方法检索你要获取得键

$john = Cache::tags([ "people"  , 'artists'  ])->get('John');

$anne = Cache::tags([ 'people' , 'authors' ])->get('Anne');

移除带有标签得缓存数据

你可能需要移除单个标签或者一组标签所标记的所有缓存数据,例如,下面这个例子将会移除带有people,authors 或者两者都有的标签的所有缓存数据,所有Anne 和 John 将会从缓存中删除:

Cache::tags( ['people' , 'authors'] )->flush();

相反,下面的例子只会移除带有标签authors 的缓存数据,因此ANne数据将会被移除,但是 John 就不会

Cache::tags('authors')->flush();

增加自定义缓存驱动

编写驱动

要创建自定义的缓存驱动,首先需要实现 Illuminate\Contracts\Cache\Store  contract 契约。因此MongoDB缓存实现看起来就像是这样

<?php

namespace App\Extensions;

use Illuminate\Contracts\Cache\Store;

class MongoStore implements Store
{
public function get($key) {}
public function many(array $keys) {}
public function put($key, $value, $seconds) {}
public function putMany(array $values, $seconds) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function forget($key) {}
public function flush() {}
public function getPrefix() {}
}

我们只需要MongoDB的连接来实现这些方法,关于如何实现 这些方法中的实例,可以通过阅读源代码Illuminate\Cache\MemcachedStore 来加以理解。一旦我们完成契约接口的实现,我们就可以通过一下的示例来完成自定义驱动的注册了。

Cache::extend('mongo' , function($app){

          return Cache::repository(new MongoStore)

})

TIp:如果你不知道该将缓存驱动的代码放在什么地方,你可以在你的app 文件夹下创建一个 Extensions 的命名空间。值得注意的是,laravel 并没有硬性规定应用程序的结构。因此你可以根据自己的喜好自由的组织你的应用程序。

 

注册驱动

在laravel 注册一个自定义的缓存,我们需要在Cache门面上使用extend方法。对Cache::extend 的掉用可以在新的laravel应用程序中自带的App\Providers\AppServiceProvider  的boot 方法中完成,或者你也可以自己创建服务提供者来存放扩展,只是不要忘记在 config/app.php 的provider 的数组中注册服务提供者。

<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
/**
* 在容器中注册绑定
*
* @return void
*/
public function register()
{
//
}

/**
* 执行服务注册后的引导
*
* @return void
*/
public function boot()
{
Cache::extend('mongo', function ($app) {
return Cache::repository(new MongoStore);
});
}
}

传递给 extend 方法的第一个参数是驱动程序的名称。该值对应 config/cache.php 配置文件中的 driver 选项。第二个参数是返回Illuminate\Cache\Repository 实例的闭包。该闭包中被传入一个$app 的实例,也就是服务容器的一个实例。

一旦你的扩展被注册以后,只需要更新配置文件 config/cache.php 的driver 选项作为自定义扩展名称即可。

事件

要在每次缓存操作时执行代码,你可以监听缓存触发的事件。通常,你应该将这些事件监听器放在EventServiceProvider中:

/**
* 应用程序的事件监听器映射
*
* @var array
*/
protected $listen = [
'Illuminate\Cache\Events\CacheHit' => [
'App\Listeners\LogCacheHit',
],

'Illuminate\Cache\Events\CacheMissed' => [
'App\Listeners\LogCacheMissed',
],

'Illuminate\Cache\Events\KeyForgotten' => [
'App\Listeners\LogKeyForgotten',
],

'Illuminate\Cache\Events\KeyWritten' => [
'App\Listeners\LogKeyWritten',
],
];

 

posted @ 2021-01-12 11:27  尚真  阅读(739)  评论(0编辑  收藏  举报