緩存是web開發(fā)中重要的一部分,我相信很多人和我一樣昂勒,經(jīng)常忽略這個(gè)問題。 隨著工作經(jīng)驗(yàn)的累積舟铜,我已經(jīng)意識(shí)到緩存是多么的重要戈盈,這里我通過 Scotch 來解釋一下它的重要性。
通過觀察發(fā)現(xiàn)谆刨,Scotch每天按照計(jì)劃發(fā)布文章塘娶,然而,上一次發(fā)布文章的24小時(shí)內(nèi)痊夭,新的文章不會(huì)被放出刁岸,因此,登陸頁面上的數(shù)據(jù)將保持24小時(shí)不變她我。 換句話說虹曙,在24小時(shí)內(nèi)( 更準(zhǔn)確的說是22-23個(gè)小時(shí))向數(shù)據(jù)庫請(qǐng)求文章數(shù)據(jù)是沒有意義的迫横。
緩存可以很好的解決這個(gè)問題,當(dāng)遇到一個(gè)頁面請(qǐng)求時(shí)酝碳,我們可以把結(jié)果緩存22個(gè)小時(shí)矾踱,只要在這個(gè)時(shí)間內(nèi)通過控制器請(qǐng)求的數(shù)據(jù),都是緩存中的數(shù)據(jù)击敌,直到緩存超時(shí)。
下面我們來看看Laravel 中緩存的基本用法拴事,然后看一個(gè)簡單的例子沃斤,試試緩存到底能帶來多大的加速。
在 Laravel 中緩存的基本用法
Laravel 使得我們可以輕松地轉(zhuǎn)換出我們想要生成緩存的方式刃宵。我們很容易修改緩存驅(qū)動(dòng)方式衡瓶。只需到 config / cache.php
來查看可用的驅(qū)動(dòng)程序:
- apc
- array
- database
- file
- memcached
- redis
你可以在 .env
文件中修改緩存驅(qū)動(dòng):
CACHE_DRIVER=file
你可以繼續(xù)嘗試修改它們而不用擔(dān)心配置,因?yàn)樗J(rèn)驅(qū)動(dòng)是
file
牲证。
Cache
facade 暴露了很多靜態(tài)方法來創(chuàng)建哮针,更新,獲取坦袍,刪除和檢查緩存內(nèi)容的存在十厢。讓我們?cè)跇?gòu)建演示應(yīng)用程序之前先了解一下這些方法。
建立/更新緩存值
我們使用 put()
方法來新增或更新緩存值捂齐。該方法必須使用 3 個(gè)參數(shù):
鍵名
鍵值
-
過期時(shí)間
單位分鐘
例如:
Cache::put('key', 'value', 10);
鍵名
是緩存的唯一標(biāo)識(shí)蛮放,需要時(shí)要用它來獲取值。
此外奠宜,我們也可以用 remember()
方法自動(dòng)獲取和更新一個(gè)緩存值包颁。該方法首先檢查 鍵名
是否存在,如果已經(jīng)創(chuàng)建則返回結(jié)果压真。否則它會(huì)創(chuàng)建新的 鍵名
娩嚼,并用閉包返回結(jié)果進(jìn)行賦值,就象下面:
Cache::remember('articles', 15, function() {
return Article::all();
});
參數(shù) 15
是要緩存的分鐘數(shù)滴肿。這樣的話岳悟,我們甚至根本不必檢查緩存是否過期。Laravel 不僅會(huì)替我們打理泼差,而且會(huì)獲取或重新生成該緩存竿音,不需要我們顯式地告訴它如何操作。
檢索緩存值
緩存的值可以通過 get()
方法去獲取拴驮,這個(gè)方法接受一個(gè)參數(shù) key
:
Cache::get('key');
檢查是否已存在key
有時(shí)候在更新或者取回緩存值之前判斷這個(gè)緩存的key是否存在是很有必要的春瞬,使用 has()
方法就可以實(shí)現(xiàn):
if (Cache::has('key')){
Cache::get('key');
} else {
Cache::put('key', $values, 10);
}
刪除緩存值
刪除緩存值可以用 forget()
方法并把需要?jiǎng)h除的 key
作為參數(shù)傳進(jìn)去:
Cache::forget('key');
我們也可以檢索緩存值并刪除它。我喜歡把這個(gè)稱為一次性緩存:
$articles = Cache::pull('key');
我們還可以使用以下命令在緩存過期前就把所有緩存清楚掉:
php artisan cache:clear
一個(gè)例子
這是一個(gè)簡單的演示套啤,主要是為了說明是否使用緩存對(duì)請(qǐng)求響應(yīng)所需要時(shí)間的影響宽气,為了讓你能更直接的了解随常,我建議你跟著教程自己來 構(gòu)建 一個(gè) Laravel 例子。
模型和表遷移
使用下面命令新建一個(gè) Article
模型:
php artisan make:model Article -m
-m
參數(shù)會(huì)自動(dòng)創(chuàng)建一個(gè) migration 萄涯,所以無需再使用 create migration 命令了绪氛,這個(gè)命令會(huì)創(chuàng)建 App/Article.php
和 database/migrations/xxxx_xx_xx_xxxxxx_create_articles_table.php
文件。
修改你的 migration 文件并添加以下兩行:
public function up() {
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
// add the following
$table->string("title");
$table->string("content");
$table->timestamps();
});
}
然后我們就可以用以下命令遷移我們的數(shù)據(jù)庫了:
php artisan migrate
填充數(shù)據(jù)庫
接下來我們需要填充文章的數(shù)據(jù)庫表涝影,在 database/seeds/DatabaseSeeder.php
中枣察,修改 run()
如下所示:
public function run() {
Model::unguard();
// use the faker library to mock some data
$faker = Faker::create();
// create 30 articles
foreach(range(1, 30) as $index) {
Article::create([
'title' => $faker->sentence(5),
'content' => $faker->paragraph(6)
]);
}
Model::reguard();
}
Laravel中包含 Faker
庫用以快速生成假數(shù)據(jù),我們可以使用PHP的 range()
方法去生成30條假數(shù)據(jù)燃逻。
接下來我們就可以通過這條 artisan 命令去填充數(shù)據(jù)庫了:
php artisan db:seed
創(chuàng)建文章控制器
接下來序目,我們可以創(chuàng)建一個(gè)處理請(qǐng)求和緩存的控制器,首先它是空的:
php artisan make:controller ArticlesController
...然后我們?cè)黾右粋€(gè)路由 app/Http/routes.php
指向這個(gè)文章控制器的 index 方法:
Route::group(['prefix' => 'api'], function() {
Route::get('articles', 'ArticlesController@index');
});
現(xiàn)在我們的數(shù)據(jù)庫都是用樣本數(shù)據(jù)建立起來的伯襟,我們可以進(jìn)行測(cè)試了猿涨。
未使用緩存的響應(yīng)
讓我們看看我們傳統(tǒng)的控制器方法是什么樣的,沒有緩存姆怪,處理響應(yīng)需要多長時(shí)間叛赚,在 index()
方法中,返回文章的資源數(shù)據(jù):
public function index() {
$articles = Articles::all();
return response()->json($articles);
}
你也可以使用 Postman 去請(qǐng)求(http://localhost/api/articles) 或者直接用瀏覽器打開稽揭,你就可以看到如下所示俺附。
請(qǐng)注意在本地開發(fā)服務(wù)器上完成此請(qǐng)求所花費(fèi)的時(shí)間。
從緩存中返回的響應(yīng)
現(xiàn)在讓我們嘗試使用緩存溪掀,看看數(shù)據(jù)響應(yīng)所花費(fèi)的時(shí)間是否會(huì)有顯著差異昙读。修改 index()
方法為:
public function index() {
$articles = Cache::remember('articles', 22*60, function() {
return Article::all();
});
return response()->json($articles);
}
現(xiàn)在我們使用 remember()
方法緩存了文章,緩存時(shí)間為 22 小時(shí)膨桥,再次運(yùn)行并觀察所花費(fèi)的時(shí)間蛮浑,可以看我的截圖:
結(jié)果和建議
在我的標(biāo)準(zhǔn)開發(fā)環(huán)境中測(cè)試得出,使用緩存時(shí)產(chǎn)生響應(yīng)所需的時(shí)間比沒有使用的時(shí)候要少:
未使用緩存
Server Hits | Time |
---|---|
1st | 4478ms |
2nd | 4232ms |
3rd | 2832ms |
4th | 3428ms |
Avg | 3742ms |
使用緩存 (File 驅(qū)動(dòng))
Server Hits | Time |
---|---|
1st | 4255ms |
2nd | 3182ms |
3rd | 2802ms |
4th | 3626ms |
Avg | 3466ms |
使用緩存 (Memcached 驅(qū)動(dòng))
Server Hits | Time |
---|---|
1st | 3626ms |
2nd | 566ms |
3rd | 1462ms |
4th | 1978ms |
Avg | 1908ms :) |
使用緩存 (Redis 驅(qū)動(dòng))
這里需要通過 composer 安裝 predis/predis 包
Server Hits | Time |
---|---|
1st | 3549ms |
2nd | 1612ms |
3rd | 920ms |
4th | 575ms |
Avg | 1664ms :) |
是不是很酷呢只嚣?這里有兩點(diǎn)需要注意:
- 即使使用了緩存沮稚,第一次請(qǐng)求響應(yīng)還是需要比較多的時(shí)間,因?yàn)楫?dāng)?shù)谝淮握?qǐng)求的時(shí)候緩存里面還是空的册舞。
- 與 file 驅(qū)動(dòng)相比蕴掏,Memcached 和 Redis 的速度更快,所以建議在項(xiàng)目較大時(shí)使用外部緩存驅(qū)動(dòng)调鲸。
結(jié)論
使用文件盛杰、數(shù)據(jù)庫作為驅(qū)動(dòng),兩者在速度上沒有很明顯的區(qū)別藐石。但是如果我們使用第三方服務(wù)作為驅(qū)動(dòng), 可以很明顯地看到性能提升即供。所以投資高速緩存是值得的。
更多現(xiàn)代化 PHP 知識(shí)于微,請(qǐng)加入 PHP / Laravel 知識(shí)社區(qū) 一起學(xué)習(xí)成長吧逗嫡。