حافظه پنهان
معرفی
برخی از وظایف بازیابی یا پردازش دادهها که توسط برنامه شما انجام میشود ممکن است به CPU فشرده یا چند ثانیه طول بکشد. در این مورد، معمول است که دادههای بازیابی شده را برای مدتی در حافظه پنهان نگه میدارند تا بتوان در درخواستهای بعدی برای همان دادهها به سرعت بازیابی شوند. دادههای کش معمولاً در یک انبار داده بسیار سریع مانند Memcached یا Redis ذخیره میشوند .
خوشبختانه، لاراول یک API گویا و یکپارچه برای پشتیبانهای کش مختلف ارائه میکند که به شما امکان میدهد از بازیابی سریع دادهها و سرعت بخشیدن به برنامه وب خود استفاده کنید.
پیکربندی
فایل پیکربندی کش برنامه شما در آدرس قرار دارد
config/cache.php
. در این فایل، میتوانید مشخص کنید که از کدام درایور کش میخواهید بهطور
پیشفرض در سراسر برنامهتان استفاده شود. لاراول از پشتیبانهای کش محبوب مانند
Memcached
،
Redis
،
DynamoDB
و پایگاههای داده رابطهای خارج از جعبه پشتیبانی میکند. علاوه بر این،
یک درایور کش مبتنی بر فایل در دسترس است، در حالی که
array
درایورهای کش "تهی" پشتیبان های کش مناسبی را برای تست های خودکار شما فراهم
می کنند.
فایل پیکربندی کش همچنین شامل گزینههای مختلف دیگری است که در داخل فایل
مستند شدهاند، بنابراین حتماً این گزینهها را بخوانید. بهطور پیشفرض، لاراول به گونهای پیکربندی شده است که
از
file
درایور حافظه پنهان استفاده کند، که اشیاء سریالسازی شده و کششده را در
سیستم فایل سرور ذخیره میکند. برای برنامه های بزرگتر، توصیه می شود از درایور قوی تری مانند Memcached یا
Redis استفاده کنید. حتی ممکن است چندین پیکربندی کش را برای یک درایور پیکربندی کنید.
پیش نیاز راننده
پایگاه داده
هنگام استفاده از
database
درایور حافظه نهان، باید جدولی را تنظیم کنید که حاوی آیتم های کش باشد.
Schema
برای جدول زیر
نمونه ای از بیانیه را خواهید دید :
Schema::create('cache', function ($table) { $table->string('key')->unique(); $table->text('value'); $table->integer('expiration');});
همچنین می توانید از
php artisan cache:table
دستور Artisan برای ایجاد یک مهاجرت با طرحواره مناسب استفاده کنید.
Memcached
استفاده از درایور Memcached مستلزم
نصب
بسته Memcached PECL
است. می توانید تمام سرورهای Memcached خود را در
config/cache.php
فایل پیکربندی فهرست کنید. این فایل از قبل حاوی یک
memcached.servers
ورودی برای شروع است:
'memcached' => [ 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 'port' => env('MEMCACHED_PORT', 11211), 'weight' => 100, ], ],],
در صورت نیاز، می توانید این
host
گزینه را روی یک مسیر سوکت یونیکس تنظیم کنید. اگر این کار را انجام دهید،
port
گزینه باید روی
0
:
'memcached' => [ [ 'host' => '/var/run/memcached/memcached.sock', 'port' => 0, 'weight' => 100 ],],
ردیس
قبل از استفاده از کش Redis با لاراول، باید افزونه PhpRedis PHP را از طریق
PECL نصب کنید یا
predis/predis
بسته (~1.0) را از طریق Composer نصب کنید.
Laravel Sail
در حال حاضر شامل این افزونه است. علاوه بر این، پلتفرم های رسمی استقرار
لاراول مانند
Laravel Forge
و
Laravel Vapor
دارای پسوند PhpRedis هستند که به طور پیش فرض نصب شده اند.
برای اطلاعات بیشتر در مورد پیکربندی Redis، به صفحه اسناد لاراول آن مراجعه کنید .
DynamoDB
قبل از استفاده از درایور کش
DynamoDB
، باید یک جدول DynamoDB برای ذخیره تمام داده های کش شده ایجاد کنید. به
طور معمول، این جدول باید نامگذاری شود
cache
. با این حال، شما باید جدول را بر اساس مقدار مقدار
stores.dynamodb.table
پیکربندی در فایل پیکربندی برنامه خود نام گذاری کنید
cache
.
این جدول همچنین باید دارای یک کلید پارتیشن رشته ای با نامی باشد که با
مقدار
stores.dynamodb.attributes.key
آیتم پیکربندی در فایل پیکربندی برنامه شما مطابقت دارد
cache
. به طور پیش فرض، کلید پارتیشن باید نامگذاری شود
key
.
استفاده از کش
به دست آوردن یک نمونه کش
برای به دست آوردن نمونه فروشگاه کش، می توانید از
Cache
نما استفاده کنید، که ما در سراسر این مستندات از آن استفاده خواهیم کرد.
نما
Cache
دسترسی راحت و مختصری به پیاده سازی های اساسی قراردادهای کش لاراول فراهم
می کند:
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Cache; class UserController extends Controller{ /** * Show a list of all users of the application. * * @return Response */ public function index() { $value = Cache::get('key'); // }}
دسترسی به چند فروشگاه کش
با استفاده از
Cache
نما، می توانید از طریق
store
روش به فروشگاه های کش مختلف دسترسی داشته باشید. کلید ارسال شده به
store
روش باید با یکی از فروشگاه های فهرست شده در آرایه پیکربندی در
فایل پیکربندی
stores
شما مطابقت داشته باشد:
cache
$value = Cache::store('file')->get('foo'); Cache::store('redis')->put('bar', 'baz', 600); // 10 Minutes
بازیابی موارد از حافظه پنهان
روش
Cache
نما
get
برای بازیابی آیتم ها از حافظه پنهان استفاده می شود. اگر مورد در کش وجود
نداشته باشد،
null
برگردانده خواهد شد. در صورت تمایل، میتوانید آرگومان دومی را به
get
متد ارسال کنید که مقدار پیشفرضی را که میخواهید در صورت عدم وجود آیتم
برگردانده شود، مشخص میکند:
$value = Cache::get('key'); $value = Cache::get('key', 'default');
حتی ممکن است بسته شدن را به عنوان مقدار پیش فرض ارسال کنید. اگر مورد مشخص شده در حافظه پنهان وجود نداشته باشد، نتیجه بسته شدن بازگردانده می شود. گذراندن یک بسته به شما امکان می دهد بازیابی مقادیر پیش فرض را از یک پایگاه داده یا سایر سرویس های خارجی به تعویق بیندازید:
$value = Cache::get('key', function () { return DB::table(/* ... */)->get();});
بررسی وجود آیتم
این
has
روش ممکن است برای تعیین وجود آیتم در حافظه پنهان استفاده شود.
false
اگر آیتم وجود داشته باشد اما مقدار آن باشد،
این متد نیز برمی گردد
null
:
if (Cache::has('key')) { //}
افزایش / کاهش ارزش ها
متدهای
increment
و
decrement
ممکن است برای تنظیم مقدار موارد اعداد صحیح در حافظه پنهان استفاده شوند.
هر دوی این روشها یک آرگومان دوم اختیاری را میپذیرند که میزان افزایش یا کاهش ارزش آیتم را نشان میدهد:
Cache::increment('key');Cache::increment('key', $amount);Cache::decrement('key');Cache::decrement('key', $amount);
بازیابی و ذخیره
گاهی اوقات ممکن است بخواهید یک مورد را از حافظه پنهان بازیابی کنید، اما
اگر مورد درخواستی وجود نداشته باشد، یک مقدار پیش فرض را نیز ذخیره کنید. به عنوان مثال، ممکن است بخواهید همه
کاربران را از حافظه پنهان بازیابی کنید یا اگر آنها وجود ندارند، آنها را از پایگاه داده بازیابی کرده و به
حافظه پنهان اضافه کنید. می توانید این کار را با استفاده از
Cache::remember
روش زیر انجام دهید:
$value = Cache::remember('users', $seconds, function () { return DB::table('users')->get();});
اگر آیتم در کش وجود نداشته باشد، بسته شدن به
remember
متد انجام می شود و نتیجه آن در کش قرار می گیرد.
میتوانید از این
rememberForever
روش برای بازیابی یک مورد از حافظه پنهان یا ذخیره آن برای همیشه در صورت
عدم وجود آن استفاده کنید:
$value = Cache::rememberForever('users', function () { return DB::table('users')->get();});
بازیابی و حذف
اگر نیاز دارید که یک مورد را از حافظه پنهان بازیابی کنید و سپس آن مورد را
حذف کنید، می توانید از این
pull
روش استفاده کنید. مانند
get
متد،
null
اگر مورد در حافظه پنهان وجود نداشته باشد، برگردانده خواهد شد:
$value = Cache::pull('key');
ذخیره اقلام در کش
می توانید از
put
روش روی
Cache
نما برای ذخیره اقلام در حافظه پنهان استفاده کنید:
Cache::put('key', 'value', $seconds = 10);
اگر زمان ذخیره سازی به روش منتقل نشود
put
، آیتم به طور نامحدود ذخیره می شود:
Cache::put('key', 'value');
به جای ارسال تعداد ثانیه ها به عنوان یک عدد صحیح، می توانید
DateTime
نمونه ای را نیز ارسال کنید که نشان دهنده زمان انقضای مورد نظر مورد ذخیره
شده در حافظه پنهان است:
Cache::put('key', 'value', now()->addMinutes(10));
در صورت عدم وجود ذخیره کنید
این
add
روش تنها زمانی مورد را به حافظه پنهان اضافه می کند که قبلاً در حافظه
پنهان وجود نداشته باشد.
true
اگر آیتم واقعاً به حافظه پنهان اضافه شود،
متد برمی گردد .
در غیر این صورت، روش برمی گردد
false
. روش
add
یک عملیات اتمی است:
Cache::add('key', 'value', $seconds);
ذخیره اقلام برای همیشه
این
forever
روش ممکن است برای ذخیره دائمی یک آیتم در حافظه پنهان استفاده شود. از
آنجایی که این موارد منقضی نمی شوند، باید به صورت دستی با استفاده از
forget
روش زیر از حافظه پنهان حذف شوند:
Cache::forever('key', 'value');
اگر از درایور Memcached استفاده میکنید، مواردی که «برای همیشه» ذخیره میشوند ممکن است وقتی حافظه پنهان به حد مجاز خود برسد حذف شوند.
حذف موارد از کش
با استفاده از روش زیر می توانید موارد را از حافظه پنهان حذف کنید
forget
:
Cache::forget('key');
همچنین میتوانید با ارائه صفر یا منفی تعداد ثانیههای انقضا، موارد را حذف کنید:
Cache::put('key', 'value', 0); Cache::put('key', 'value', -5);
می توانید کل کش را با استفاده از
flush
روش زیر پاک کنید:
Cache::flush();
شستشوی کش به «پیشوند» کش پیکربندی شده شما احترام نمی گذارد و همه ورودی ها را از کش حذف می کند. هنگام پاک کردن حافظه پنهانی که توسط سایر برنامه ها به اشتراک گذاشته شده است، به دقت در نظر بگیرید.
کمک کننده حافظه پنهان
علاوه بر استفاده از
Cache
نما، میتوانید از
cache
تابع سراسری برای بازیابی و ذخیره دادهها از طریق حافظه پنهان نیز استفاده
کنید. هنگامی که
cache
تابع با یک آرگومان رشته ای فراخوانی می شود، مقدار کلید داده شده را برمی
گرداند:
$value = cache('key');
اگر آرایهای از جفتهای کلید/مقدار و زمان انقضا را برای تابع ارائه دهید، مقادیر را برای مدت زمان مشخص در حافظه پنهان ذخیره میکند:
cache(['key' => 'value'], $seconds); cache(['key' => 'value'], now()->addMinutes(10));
وقتی
cache
تابع بدون هیچ آرگومان فراخوانی میشود، نمونهای از
Illuminate\Contracts\Cache\Factory
پیادهسازی را برمیگرداند و به شما این امکان را میدهد که سایر روشهای کش
را فراخوانی کنید:
cache()->remember('users', $seconds, function () { return DB::table('users')->get();});
هنگام آزمایش فراخوانی
cache
تابع سراسری، میتوانید از اینCache::shouldReceive
روش استفاده کنید، درست مثل اینکه در حال آزمایش نما هستید .
برچسب های کش
file
هنگام استفاده از ,dynamodb
یا درایورهای کش پشتیبانی نمی شودdatabase
. علاوه بر این، هنگام استفاده از چندین تگ با حافظه پنهان که "برای همیشه" ذخیره می شوند، عملکرد بهتری با درایوری مانندmemcached
, که به طور خودکار رکوردهای قدیمی را پاک می کند، خواهد بود.
ذخیره اقلام کش برچسب گذاری شده
تگ های کش به شما این امکان را می دهند که آیتم های مرتبط را در حافظه پنهان
برچسب گذاری کنید و سپس تمام مقادیر کش شده را که به یک تگ اختصاص داده شده اند، شستشو دهید. شما می توانید با
ارسال یک آرایه مرتب شده از نام برچسب ها به یک حافظه پنهان برچسب گذاری شده دسترسی پیدا کنید. به عنوان مثال،
اجازه دهید به یک کش برچسب گذاری شده و
put
یک مقدار در حافظه پنهان دسترسی پیدا کنیم:
Cache::tags(['people', 'artists'])->put('John', $john, $seconds); Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);
دسترسی به آیتم های کش برچسب گذاری شده
مواردی که از طریق برچسبها ذخیره میشوند، بدون ارائه برچسبهایی که برای
ذخیره مقدار استفاده شدهاند، قابل دسترسی نیستند. برای بازیابی یک آیتم کش برچسب گذاری شده، همان لیست مرتب شده
برچسب ها را به
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();
قفل اتمی
برای استفاده از این ویژگی، برنامه شما باید از
memcached
,redis
,dynamodb
,database
,file
یاarray
کش به عنوان درایور کش پیش فرض برنامه شما استفاده کند. علاوه بر این، همه سرورها باید با یک سرور حافظه مرکزی یکسان در ارتباط باشند.
پیش نیاز راننده
پایگاه داده
هنگام استفاده از
database
درایور کش، باید جدولی را تنظیم کنید که حاوی قفل های کش برنامه شما باشد.
Schema
برای جدول زیر
نمونه ای از بیانیه را خواهید دید :
Schema::create('cache_locks', function ($table) { $table->string('key')->primary(); $table->string('owner'); $table->integer('expiration');});
مدیریت قفل ها
قفل های اتمی امکان دستکاری قفل های توزیع شده را بدون نگرانی در مورد شرایط
مسابقه فراهم می کنند. به عنوان مثال،
لاراول فورج
از قفل های اتمی استفاده می کند تا اطمینان حاصل کند که تنها یک وظیفه از
راه دور در یک سرور در یک زمان اجرا می شود. شما می توانید قفل ها را با استفاده از روش زیر ایجاد و مدیریت کنید
Cache::lock
:
use Illuminate\Support\Facades\Cache; $lock = Cache::lock('foo', 10); if ($lock->get()) { // Lock acquired for 10 seconds... $lock->release();}
روش
get
بسته شدن را نیز می پذیرد. پس از اجرای بسته شدن، لاراول به طور خودکار قفل
را آزاد می کند:
Cache::lock('foo', 10)->get(function () { // Lock acquired for 10 seconds and automatically released...});
اگر قفل در لحظه ای که شما آن را درخواست می کنید در دسترس نیست، می توانید
به لاراول دستور دهید که برای تعداد مشخصی از ثانیه صبر کند. اگر نتوان قفل را در مدت زمان مشخص شده بدست آورد،
یک عدد
Illuminate\Contracts\Cache\LockTimeoutException
پرتاب می شود:
use Illuminate\Contracts\Cache\LockTimeoutException; $lock = Cache::lock('foo', 10); try { $lock->block(5); // Lock acquired after waiting a maximum of 5 seconds...} catch (LockTimeoutException $e) { // Unable to acquire lock...} finally { optional($lock)->release();}
مثال بالا ممکن است با عبور دادن یک بسته به
block
روش ساده شود. هنگامی که یک بسته به این روش منتقل می شود، لاراول تلاش می
کند تا قفل را برای تعداد ثانیه مشخص شده بدست آورد و پس از اجرای بسته شدن به طور خودکار قفل را آزاد می کند:
Cache::lock('foo', 10)->block(5, function () { // Lock acquired after waiting a maximum of 5 seconds...});
مدیریت قفل ها در سراسر فرآیندها
گاهی اوقات، ممکن است بخواهید در یک فرآیند یک قفل را بدست آورید و در فرآیندی دیگر آن را آزاد کنید. به عنوان مثال، ممکن است در طول یک درخواست وب، قفلی را به دست آورید و بخواهید در پایان یک کار در صف که توسط آن درخواست ایجاد می شود، قفل را آزاد کنید. در این سناریو، شما باید "Token مالک" قفل را به کار در صف ارسال کنید تا کار بتواند با استفاده از نشانه داده شده، قفل را مجدداً نمونه برداری کند.
در مثال زیر، اگر یک قفل با موفقیت به دست آمد، یک کار در صف ارسال می کنیم.
علاوه بر این، توکن مالک قفل را از طریق روش قفل به کار در صف ارسال می کنیم
owner
:
$podcast = Podcast::find($id); $lock = Cache::lock('processing', 120); if ($lock->get()) { ProcessPodcast::dispatch($podcast, $lock->owner());}
در کار برنامه ما
ProcessPodcast
، میتوانیم قفل را با استفاده از توکن مالک بازیابی و آزاد کنیم:
Cache::restoreLock('processing', $this->owner)->release();
اگر می خواهید یک قفل را بدون احترام به صاحب فعلی آن آزاد کنید، می توانید
از
forceRelease
روش زیر استفاده کنید:
Cache::lock('processing')->forceRelease();
افزودن درایورهای کش سفارشی
نوشتن راننده
برای ایجاد درایور کش سفارشی خود، ابتدا باید
Illuminate\Contracts\Cache\Store
قرارداد را
پیاده سازی کنیم . بنابراین، یک پیاده سازی کش 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
:
Cache::extend('mongo', function ($app) { return Cache::repository(new MongoStore);});
اگر نمیخواهید کد درایور کش سفارشی خود را کجا قرار دهید، میتوانید یک
Extensions
فضای نام درapp
فهرست خود ایجاد کنید. با این حال، به خاطر داشته باشید که لاراول ساختار نرم افزاری سفت و سختی ندارد و شما آزاد هستید که برنامه خود را بر اساس ترجیحات خود سازماندهی کنید.
ثبت نام درایور
برای ثبت درایور کش سفارشی با لاراول
extend
از روش
Cache
نما استفاده می کنیم. از آنجایی که سایر ارائه دهندگان خدمات ممکن است سعی
کنند مقادیر ذخیره شده را در روش خود بخوانند
boot
، ما درایور سفارشی خود را در یک
booting
تماس برگشتی ثبت می کنیم. با استفاده از
booting
callback، میتوانیم اطمینان حاصل کنیم که درایور سفارشی درست قبل از
boot
فراخوانی متد در ارائهدهندگان خدمات برنامه ما ثبت شده است، اما پس از
register
فراخوانی متد در همه ارائهدهندگان خدمات. ما
booting
callback خود را در
register
متد کلاس برنامه خود ثبت می کنیم
App\Providers\AppServiceProvider
:
<?php namespace App\Providers; use App\Extensions\MongoStore;use Illuminate\Support\Facades\Cache;use Illuminate\Support\ServiceProvider; class CacheServiceProvider extends ServiceProvider{ /** * Register any application services. * * @return void */ public function register() { $this->app->booting(function () { Cache::extend('mongo', function ($app) { return Cache::repository(new MongoStore); }); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // }}
اولین آرگومان ارسال شده به
extend
متد، نام درایور است. این با
driver
گزینه شما در فایل پیکربندی
مطابقت دارد
config/cache.php
. آرگومان دوم بسته شدن است که باید یک
Illuminate\Cache\Repository
نمونه را برگرداند. بسته شدن یک نمونه ارسال میشود
$app
، که نمونهای از
کانتینر سرویس
است .
پس از ثبت برنامه افزودنی، گزینه
config/cache.php
فایل پیکربندی خود
driver
را به نام برنامه افزودنی خود به روز کنید.
مناسبت ها
برای اجرای کد در هر عملیات کش، می توانید به
رویدادهایی که
توسط حافظه پنهان شلیک می شوند گوش دهید. به طور معمول، شما باید این
شنوندگان رویداد را در کلاس برنامه خود قرار دهید
App\Providers\EventServiceProvider
:
use App\Listeners\LogCacheHit;use App\Listeners\LogCacheMissed;use App\Listeners\LogKeyForgotten;use App\Listeners\LogKeyWritten;use Illuminate\Cache\Events\CacheHit;use Illuminate\Cache\Events\CacheMissed;use Illuminate\Cache\Events\KeyForgotten;use Illuminate\Cache\Events\KeyWritten; /** * The event listener mappings for the application. * * @var array */protected $listen = [ CacheHit::class => [ LogCacheHit::class, ], CacheMissed::class => [ LogCacheMissed::class, ], KeyForgotten::class => [ LogKeyForgotten::class, ], KeyWritten::class => [ LogKeyWritten::class, ],];