缓存可以大大减少数据库查询操作以减轻服务器的压力,特别是一些短时间内的大量任务执行(搜索、点赞、文章查看数更新等),像这样频繁对数据库操作会产生大量的查询,我们可以将其缓存起来,在服务器空闲的时候批量操作,这样我们就使用缓存系统来完成,Larave的缓存特别的强大,如果在 config/cache.php 里未配置使用更高性能的Redis、Memcached类软件时,默认将内容缓存到storage/framework/cache/data文件夹里。
在正常的项目中,我们都会使用到mysql数据库(如果使用默认的文件缓存则可以使用默认即可),而以不想安装Redis的情况下(Redis我个人超爱,缓存到内存里,速度可以起飞),首先快速了解一下Laravel为我们提供的各种方法:
这里只是针对提供的方法快速浏览,要了解缓存使用的详细方法,请继续看下面的内容!
文章缓存实例:http://www.55mx.com/php/214.html
找到config/cache.php里的default,并修改为下面的database缓存项:
'default' => env('CACHE_DRIVER', 'database'),
然后使用artisan生成可迁移的缓存表:
php artisan cache:table
执行上面的命令后,会在database/migrations目录生成一个当前日期的迁移表,如我刚才生成的名字为:database/migrations/2022_04_05_062757_create_cache_table.php,然后使用表迁移命令:
php artisan migrate --env=local --path=./database/migrations/2022_04_05_062757_create_cache_table.php
映射到我们配置的mysql中,通过迁移文件就可以得到生成的表结构:
public function up()
{
//创建cache表(实际缓存)
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary(); //key为主键
$table->mediumText('value'); //使用mediumText缓存内容
$table->integer('expiration'); //缓存有效期(过期时间)
});
//创建cache_locks表(原子锁)
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary(); //要锁定的key
$table->string('owner'); //所有者
$table->integer('expiration'); //锁定时间
});
}
进入mysql可以看到多出来了上面迁移的2个表,结果按注释一样。做好上面的准备工作后,我们就可以对缓存进行CRUD操作了(增删改查)。
PS:我为什么要使用mysql做为缓存而不使用默认的文件 ,当前使用文件只上了上面的配置,但要清理缓存的时候会比较麻烦,我使用mysql的主要目的是可以使用1行命令清空缓存表即可。
Laravel的缓存底层实际位于Facade里的Cache操作类里,所以在使用前我们应该先引包:
<?php
namespace AppHttpControllers;
use IlluminateSupportFacadesCache;//引入缓存操作包
class UserController extends Controller
{
public function index()
{
$value = Cache::get('key');//获取key缓存
}
}
我们通过->get()方法获取key缓存,如果缓存并不存在或者已过期的情况下,则会返回一个null。我们可以设置->get()的第2个参数将其做为默认值:
$value = Cache::get('key', '默认值');
默认值支持使用一个闭包来实现更高级的操作:
$value = Cache::get('key', function () {
return DB::table(...)->get();//当key不存在在执行此闭包
});
使用->put()方法将数据缓存起来:
Cache::put('url', 'https://www.meishiq.com');//缓存一个url键
如果未指定第二个参数,即有效期时,则为长期有效哦~
上面忘记设置有效期了,下面可以通过再次设置使用第2参数指定有效期:
Cache::put('url', 'http://www.55mx.com/', now()->addMinutes(10));//有效时间为10分钟
有时候我们我们需要检测数据是否存在,如果存在就不存了,不存在的时候才缓存数据,可以使用->add()方法:
Cache::add('key', 'value', $seconds);//$seconds为有效期,单位秒
如果需要设置一个永久有效的缓存时,我们通常使用->forever()方法:
Cache::forever('key', 'value');//如果要删除此缓存需要使用下面的forget方法哦
小提示:如果您使用的是 Memcached 驱动程序,则当缓存达到其大小限制时,可能会删除「永久」存储的项目。
如果缓存不在使用时,我们需要通过-> forget()方法将其释放掉以节约资源:
Cache::forget('key');//删除key
当然也可以通过put将缓存时间改为负数或者为0也能自动释放掉。
如果缓存的项有点多,我们需要通过:
Cache::flush();//清空缓存
注意:刷新缓存不会考虑您配置的缓存「前缀」,并且会从缓存中删除所有条目。在清除由其他应用程序共享的缓存时,请仔细考虑这一点。
increment 和 decrement 方法可用于调整缓存中整数项的值。这两种方法都接受一个可选的第二个参数,指示增加或减少项目值的数量:
Cache::increment('key');//key++
Cache::increment('key', $amount);//key = key + $amount
Cache::decrement('key');//key--
Cache::decrement('key', $amount);//key = key - $amount
如果要检测缓存是否可用时我们需要使用到->has()方法,当key存在返回true,过期或者为空时返回false:
if (Cache::has('key')) {
//key存在才执行里面的代码
}
在上面的缓存基本操作里我们将数据存在了数据库里,但我们又想临时使用一下file或者其它缓存时,我们可以通过调用store方法指定要操作的缓存存储引擎:
$value = Cache::store('file')->get('foo');//获取file里的缓存
Cache::store('redis')->put('bar', 'baz', 600); //将缓存到Redis里,有效期10分钟
有时候我们需要使用缓存里的一个设置值,存在则返回,不存在时,我们需要通过从数据库里查询并缓存起来:
//尝试通过remember从缓存里读取缓存
$settings = Cache::remember('settings', $seconds, function () {
return DB::table('settings')->get();//缓存不存在从数据库里获取设置项存缓存起来,有效期$seconds
});
上面的$seconds指定了缓存的有效时,如果你希望可以长时间缓存,则可以将上面的remember替换为rememberForever(将缓存999999999秒):
//rememberForever不需要设置缓存时间
$value = Cache::rememberForever('users', function () {
return DB::table('users')->get();
});
当我们设置缓存只用一次就无效的场景时,可以使用->pull()方法,使用起来与->get()方法一样:
$value = Cache::pull('key');//查询到key返回给$value并删除key缓存,如果缓存并不存在时,返回null
使用全局的助手函数可以快速的调用缓存方法:
$value = cache('key');//获取key
cache(['key' => 'value'], $seconds);//设置key=value,有效期$seconds
cache(['key' => 'value'], now()->addMinutes(10));//设置key=value,有效期10分钟
当不带任何参数调用 cache 函数时,它会返回 IlluminateContractsCacheFactory 实现的实例,允许您调用其他缓存方法:
//同上面的cache:: remember
cache()->remember('users', $seconds, function () {
return DB::table('users')->get();
});
缓存标签允许您在缓存中标记相关项目,然后刷新所有已分配给定标签的缓存值。您可以通过传入标记名称的有序数组来访问标记缓存。例如,让我们访问一个标记的缓存并将一个值「put」缓存中:
Cache::tags(['people', 'artists'])->put('John', $john, $seconds);//设置people的artist项为John= $john
Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);
如果要获取上面的设置项:
$john = Cache::tags(['people', 'artists'])->get('John');//获取刚才设置的$john
$anne = Cache::tags(['people', 'authors'])->get('Anne');
查询后我们不再需要时,可以通过->flush()方法清除缓存:
Cache::tags(['people', 'authors'])->flush();
//相反,此语句将仅删除带有 authors 标记的缓存值,因此将删除 Anne,但不会删除 John:
Cache::tags('authors')->flush();
多核编程中,由于并发的问题,可以会同时操作一个数据库,缓存也可能被多个请求同时操作,为了保存数据的原子性,我们可以使用原子锁功能,将重要的数据锁定起来,不让其它请求破坏。在上面的迁移表中,Laravel为我们生成了一个原子锁表,我们可以通过 Cache::lock 方法来创建与管理锁:
$lock = Cache::lock('foo', 10);//锁定foo,时间10秒
if ($lock->get()) {
//10 秒后才能返回此数据 ...
$lock->release();
}
get 方法也接受一个闭包。闭包执行后,Laravel 会自动释放锁:
Cache::lock('foo')->get(function () {
// 锁定无限期获得并自动释放...
});
如果在您请求时锁不可用,您可以指示 Laravel 等待指定的秒数。如果在指定的时间限制内无法获取锁,则会抛出LockTimeoutException异常,所以我们应该使用try来处理:
use IlluminateContractsCacheLockTimeoutException;
$lock = Cache::lock('foo', 10);
try {
$lock->block(5);
// 等待最多 5 秒后获得锁定...
} catch (LockTimeoutException $e) {
// 无法获取锁...
} finally {
optional($lock)->release();
}
上面的例子可以通过将闭包传递给 block 方法来简化。当一个闭包被传递给这个方法时,Laravel 将尝试在指定的秒数内获取锁,并在闭包执行后自动释放锁:
Cache::lock('foo', 10)->block(5, function () {
// 等待最多 5 秒后获得锁定...
});
跨进程管理锁:有时,您可能希望在一个进程中获取锁并在另一个进程中释放它。例如,您可能在 Web 请求期间获取锁,并希望在由该请求触发的排队作业结束时释放锁。在这种情况下,您应该将锁的作用域「owner 令牌」传递给排队的作业,以便作业可以使用给定的令牌重新实例化锁。
$podcast = Podcast::find($id);//排队作业ID
$lock = Cache::lock('processing', 120);//锁定120秒
if ($lock->get()) {
ProcessPodcast::dispatch($podcast, $lock->owner());//通过锁的 owner 方法将锁的所有者令牌传递给排队的作业
}
在我们应用程序的 ProcessPodcast 作业中,我们可以使用所有者令牌恢复和释放锁:
Cache::restoreLock('processing', $this->owner)->release();//恢复锁并返回
Cache::lock('processing')->forceRelease();//不考虑它的当前所有者
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/207
《【Laravel笔记】缓存的使用详解》的网友评论(0)