laravel keširanje

Sve o Laravel keširanju

Keširanje je od izuzetne važnosti kada je u pitanju postizanje visokih performansi i obezbeđivanje skalabilnosti web aplikacija. Implementiranje odgovarajuće strategije keširanja, još tokom faze razvoja, je od ključne važnosti za postizanje brzog učitavanja API-a i stranica vašeg web sajta.

Laravel je bez sumnje jedan od najpopularnijih PHP framework-ova, pa je implemenacija optimalne strategije keširanja u Laravel-u neophodno za postizanje boljeg korisničkog iskustva posetilaca vašeg web sajta/aplikacije.

Zato ćemo u ovom tekstu predstaviti neke od strategija za implementaciju i upravljanje keširanjem u Laravel-u.

Zašto je keširanje važno?

Sa razvojem online biznisa, kompanije su ubrzo uvidele da sporo učitavanje web sajta i njegove loše performanse mogu da imaju prilično negativan uticaj na korisničko angažovanje na sajtu i stopu konverzije (uglavnom na stopu kupovine proizvoda i usluga koje taj biznis prodaje online). Ove loše karakteristike mogu da ostave dugoročne posledice i na rangiranje vašeg sajta u Google pretragama, što znači da će vremenom korisnici sve manje pronalaziti vaš sajt po ključnim rečima koje se odnose na vaš biznis. To svakako nisu dobre vesti za bilo kog vlasnika sajta.

Istraživanja su pokazala da bi 25% korisnika napustilo neki sajt ukoliko bi učitavanje stranice trajalo duže od 4 sekunde, a čak 46% ne bi ponovo posetilo sajt koji ima loše performanse (sporo radi, sporo se učitava, dugo se čeka na odgovor sa servera i sl).

Kada su u pitanju mobilni uređaji, čak 74% posetilaca  koji sajtu pristupaju na ovaj način, bi napustilo taj sajt ukoliko bi stranici trebalo duže od 5 sekundi da se učita.

Da biste razumeli koliko brzina učitavanja može da utiče na uspeh nekog online biznisa, navešćemo samo primer kompanije Amazon, koja je izračunala da bi samo jedna sekunda kašnjenja u učitavanju stranice, mogla da im prouzrokuje gubitak od neverovatnih 1.6 milijardi dolara godišnje!

Znači, čak i neznatno kašnjenje u učitavanju stranice vašeg web sajta, može imati veliki negativan uticaj na korisničko iskustvo vaših korisnika, a kod velikih kompanija i do prilično velikog pada online prodaje.

Šta je Laravel keširanje?

Laravel omogućava laku implementaciju keširanja, jer jednostavno možete prelaziti sa jednog na drugi caching engine, bez potrebe za pisanjem koda.

Konfiguraciju Laravel keša možete pronaći unutar config/cache.php foldera, iako će vam biti potreban samo .env fajl da biste prelazili između različitih backend-a za keširanje.

Laravel keš drajveri

Laravel keš ima napredne drajvere za keširanje. U zavisnosti od konkretnog slučaja, možete da prelazite sa jednog na drugi drajver kako biste poboljšali performanse i vreme učlitavanja vaše aplikacije.

S tim u vezi, Laravel keš takođe obezbeđuje jednostavan način za kreiranje prilagođenog backend-a i za njegovo korišćenje sa Laravel kešom. Zato hajde da pogledamo listu najkorisnijih drajvera.

Fajl

Fajl drajver je podrazumevani backend koji Laravel keš koristi u situaciji kada nijedan drajver nije naveden u .env fajlu.

Fajl backend je dizajniran da čuva keširane podatke u enkriptovanom fajlu koji se nalazi na lokaciji storage/framework. Laravel kreira enkriptovani fajl sa podacima i keš ključ, kada su novi podaci keširani. Isto se dešava kada korisnik pokušava da dohvati sadržaj. Laravel keš traži navedeni ključ kroz folder i ako ga pronađe vraća sadržaj ka korisniku.

Iako fajl backend besprekorno radi i štedi vreme za instalaciju i konfigurisanje eksternih drajvera, on takođe može biti dobar izbor za development. On je brži nego kada pristupate podacima direktno sa servera baze podataka.

Da biste koristili fajl drajver dodajte sledeći kod u vaš .env fajl:

CACHE_DRIVER=file

Niz (array)

Niz drajver je savršen backend za pokretanje automatizovanih testova i konfiguriše se veoma jednostavno pomoću Github Actions, Jenkins, etc.

Niz backend čuva keširane podatke u nizu u PHP-u i ne zahteva da instalirate ili konfigurišete bilo kakve drajvere. Odličan je izbor za automatizovane testove i nešto je brži od fajl keš backend-a.

Da biste koristili niz drajver, dodajte sledeći kod u vaš .env fajl:

CACHE_DRIVER=array

Baza podataka (database)

Kada koristite baza podataka drajver, podaci se čuvaju u memoriji za trenutni PHP proces. Iz tog razloga je potrebno da kreirate tabelu u bazi podataka da biste sačuvali keširane podatke.

Dodatno, baza podataka keširanje poboljšava skalabilnost tako što distribuira upite sa backend-a na nekoliko frontend-ova.

Možete da pokrenete ovu Artisan komandu – php artisan cache:table – da biste generisali šemu baze podataka potrebnu za rad baza podataka drajvera.

Baza podataka drajver se koristi uglavnom u situacijama u kojima možete instalirati bilo koji softver na vašu hosting platformu.

Na primer, recimo da koristite besplatni hosting plan sa ograničenim opcijama. Za tu priliku preporučujemo da izaberete opciju da radite sa fajl drajverom, zato što je u najvećem broju slučajeva baza podataka drajver najslabija tačka vaše aplikacije. Guranje dodatnih podataka u to usko grlo svakako nije dobra ideja.

Da biste koristili baza podataka drajver, dodajte sledeći kod u vaš .env fajl:

CACHE_DRIVER=database

Redis

Redis drajver koristi in-memory zasnovanu tehnologiju keširanja pod nazivom Redis. Iako je brz u poređenju sa drugim prethodno pomenutim keš drajverima, on zahteva instalaciju i konfigurisanje eksterne tehnologije.

Da biste koristili redis drajver, dodajte sledeći kod u vaš .env fajl:

CACHE_DRIVER=redis

Memcached

Memcached je verovatno najpoznatiji in-memory zasnovan cache-store. Ukoliko vam dodatno konfigurisanje i održavanje servera ne predstavlja neki problem, Memcached je odličan izbor.

Korišćenje memcached drajvera zahteva da bude instaliran Memcached PECL paket.

Da biste koristili memcached drajver, dodajte sledeći kod u vaš .env fajl.

CACHE_DRIVER=memcached

Laravel keš metode

Laravel donosi mnoge korisne metode koje se koriste za implementaciju različitih kešing strategija.

Ispod je lista i objašnjenje različitih metoda (kategorisanih prema njihovim različitim namenama)

  • put()
  • get()
  • many()
  • putMany()
  • increment()
  • decrement()
  • forever()
  • forget()
  • flush()
  • remember()
  • rememberForever()

Čuvanje keša

Čuvanje novih podataka u kešu je veoma jednostavno koristeći različite metode, svaka sa nekoliko upotrebnih slučajeva.

Cache::put()

Ova metoda prihvata tri parametra: key, data koji će biti smešteni u keš i duration.

Pogledajmo kako koristiti Cache::put():

Cache::put(key, data, duration) 
$post = Post::find(1); 
Cache::put('post_1', $post, 20);

Kod iznad će keširati post sa jedinstvenim ključem na 20 sekundi.

Cache::putMany()

Ova metoda smešta niz podataka u keš odjednom sa istim trajanjem. Prihvata dva parametra, data i duration (u sekundama).

Pogledajmo kako da koristite Cache::putMany():

Cache::putMany(data, duration) // syntax 
$posts = Post::all(); 
Cache::putMany($posts, 20);

Cache::remember()

Ova metoda je još jedan odličan način da se implementira strategija keširanja. Metoda Cache::remember() prihvata tri parametra, key, duration i closure (zatvaranje) koje se koristi za dobijanje podataka iz baze podataka ako nisu pronađeni.

Pogledajmo kako da koristite Cache::remember():

Cache::remember(key, duration, closure) // syntax 
Cache::remember('posts', 20, function()
{ return Post::all(); 
});

Laravel keš takođe ima metodu Cache::rememberForever(), koja ne prihvata parametar duration i podatke čuva zauvek.

Cache::forever()

Ova metoda čuva podatke u keš serveru zauvek bez navođenja trajanja. Možete je implementirati koristeći sledeći kod:

Cache::forever(key, data) 
$post = Post::find(1); 
Cache::forever('post_1', $post);

Povlačenje podataka iz keša

Metode u ovoj kategoriji povlače podatke iz keša. Neke od ovih metoda mogu se ponašati različito u zavisnosti od toga da li su podaci pronađeni ili ne.

Cache::get()

Ova metoda povlači podatke iz keš servera sa određenim ključem. Možete povući stavku koristeći sledeći kod:

Cache::get(key) // syntax 
$posts = Cache::get('posts');

Cache::many()

Ova metoda je slična metodi Cache::putMany(). Koristi se za povlačenje niza keširanih podataka odjednom koristeći niz keširanih ključeva. Možete povući niz keša koristeći sledeći kod:

Cache::many(keys) // syntax 
const $keys = [ 
'posts', 'post_1', 'post_2' 
]; $posts = Cache::many($keys);

Cache::remember()

Možete koristiti i ovu metodu da povučete keširane podatke proveravajući keš server koristeći pruženi ključ. Ako su podaci smešteni u kešu, povući će ih. U suprotnom, povući će podatke sa servera baze podataka i keširati ih. Ova metoda je ista kao i metoda Cache::rememberForever() sa dodatnim parametrom sekunde u metodi Cache::remember().

Uklanjanje stavki iz keša

Metode u ovoj kategoriji se koriste za uklanjanje stavki iz keša, grupisanih po funkcionalnosti.

Cache::forget()

Ova metoda uklanja pojedinačnu stavku iz keša sa određenim ključnim parametrom:

Cache::forget('key');

Cache::flush()

Ova metoda briše sve keš drajvere. Brise sve stavke smeštene bilo gde u kešu:

Cache::flush();

Povećavanje ili smanjivanje vrednosti keša

Možete prilagoditi vrednosti celobrojne vrednosti smeštene u vašem kešu koristeći metode povećanja i smanjenja, redom:

Cache::increment('key'); 
Cache::increment('key', $amount); 
Cache::decrement('key'); 
Cache::decrement('key', $amount);

Laravel keš ima još mnogo odličnih metoda koje nismo ovde predstavili, ali su dovoljne i ove koje smo vam ovde opisali, jer spadaju u najpopularnije i najčešće korišćene. Pregled svih metoda možete naći u zvaničnoj Laravel keš dokumentaciji.

Objašnjenje keš naredbi

Laravel implmentira naredbe kako bi rad sa Laravel kešom bio lak i brz. U nastavku je lista svih naredbi i njihovih funkcionalnosti.

Brisanje Laravel keša

Ova naredba se koristi za brisanje Laravel keša pre nego što on istekne. Koristi terminal ili konzolu. Na primer, možete pokrenuti sledeću naredbu:

php artisan cache:clear

Brisanje route-keša

Ova naredba se koristi za brisanje route-keša vaše Laravel aplikacije. Na primer, pokrenite sledeću naredbu da obrišete route-keš:

php artisan config:clear

Brisanje kompajliranih fajlova prikaza

Ova naredba se koristi za brisanje kompajliranih fajlova prikaza (view) vaše Laravel aplikacije:

php artisan view:clear

Tabela baze podataka

Kada koristite drajver baze podataka, potrebno je da kreirate keš šemu baze podataka kako biste sačuvali keš podatke. Takođe možete koristiti Artisan naredbu da generišete migraciju sa odgovarajućom šemom:

php artisan cache:table

Laravel strategije keširanja

U zavisnosti od potreba vaše aplikacije i strukture podataka, na raspolaganju vam stoji nekoliko strategija keširanja. Čak možete kreirati i prilagođenu strategiju koja najviše odgovara vašim potrebama. Sada ćemo proći kroz listu popularnih strategija keširanja koje možete da primenite u vašem sledećem Laravel projektu.

writeThrough

U writeThrough strategiji, keš server se nalazi između zahteva i servera baze podataka, čineći da svaka operacija upisa prolazi kroz keš server pre nego što stigne do servera baze podataka. Dakle, strategija keširanja writeThrough slična je strategiji readThrough.

Ovu strategiju možete implementirati u Laravel kešu koristeći sledeći kod:

public function writeThrough($key, $data, $minutes) { 
$cacheData = Cache::put($key, $data, $minutes)
// Database Server is called from(after) the Cache Server. 
$this->storeToDB($cachedData) 
return $cacheData 
} 
private function storeToDB($data){ 
Database::create($data) 
return true 
}

writeBack (writeBehind)

Ova strategija je napredniji način implementiranja strategije writeThrough dodavanjem odlaganja operacija upisa.

Takođe je možemo nazvati strategijom writeBehind zbog odlaganja vremena koje se primenjuje na keš server pre upisivanja podataka na server baze podataka.

Ovu strategiju možete implementirati u Laravel kešu koristeći sledeći kod:

$durationToFlush = 1; // (in minute) 
$tempDataToFlush = []; 
public function writeBack($key, $data, $minutes){ 
return $this->writeThrough($key, $data, $minutes); 
} 
public function writeThrough($key, $data, $minutes) { 
$cacheData = Cache::put($key, $data, $minutes); 
$this->storeForUpdates($cacheData); 
return $cacheData; 
} 
// Stores new data to temp Array for updating 
private function storeForUpdates($data){ 
$tempData = {}; 
$tempData['duration'] = this.getMinutesInMilli(); 
$tempData['data'] = data; 
array_push($tempDataToFlush, data); 
} 
// Converts minutes to millisecond 
private function getMinutesInMilli(){ 
$currentDate = now(); 
$futureDate = Carbon(Carbon::now()->timestamp + $this->durationToFlush * 60000) 
return $futureDate->timestamp } 

// Calls to update the Database Server. 
public function updateDatabaseServer(){ 
if($this->tempDataToFlush){ foreach($this->tempDataToFlush as $index => $obj){ 
if($obj->duration timestamp){ 
if(Database::create($obj->data)){ 
array_splice($this->tempDataToFlush, $index, 1); 
    } 
   } 
  } 
 } 
}

Metoda writeBack poziva metodu writeThrough, koja smešta podatke u keš server i privremeni niz koji će kasnije biti prosleđen serveru baze podataka koristeći metodu updateDatabaseServer. Možete postaviti CronJob da ažurira server baze podataka svakih pet minuta.

writeAround

Ova strategija omogućava da sve operacije upisa idu direktno ka serveru baze podataka bez ažuriranja keš servera — samo tokom operacija čitanja keš server se ažurira.

Pretpostavimo da korisnik želi da kreira novi članak, članak se direktno čuva na serveru baze podataka. Kada korisnik želi da pročita sadržaj članka prvi put, članak se povlači sa servera baze podataka i ažurira keš server za sledeće zahteve.

Ovu strategiju možete implementirati u Laravel kešu koristeći sledeći kod:

public function writeAround($data) { 
$storedData = Database::create($data); 
return $storedData; 
} 
public function readOperation($key, $minutes){ 
$cacheData = Cache::remember($key, $minutes, function() { 
return Article::all(); 
}) 
return $cacheData; }

Cache aside (lazy loading)

Kod ove strategije aplikacija zahteva podatke prvo sa keš servera. Zatim, ako je podatak pronađen, on se vraća korisniku. U suprotnom, ako podatak nije pronađen, server baze podataka zahteva podatke i ažurira keš server za sledeće zahteve.

Ovu strategiju možete implementirati u Laravel kešu koristeći sledeći kod:

public function lazyLoadingStrategy($key, $minutes, $callback) { 
if (Cache::has($key)) { 
$data = Cache::get($key); return $data; 
} else { 
// Database Server is called outside the Cache Server. 
$data = $callback(); 
Cache::set($key, $data, $minutes); 
return $data; 
 } 
}

Gore navedeni kod pokazuje implementaciju cache aside strategije, koja je ekvivalentna implementaciji metode Cache::remember.

Read through

Ova strategija je direktni suprotni ekvivalent cache aside strategije. U ovoj strategiji, keš server se nalazi između zahteva korisnika i servera baze podataka.

Zahtevi idu direktno ka keš serveru, i keš server je odgovoran za povlačenje podataka sa servera baze podataka ako nisu pronađeni na keš serveru.

Ovu strategiju možete implementirati u Laravel kešu koristeći sledeći kod:

public function readThrough($key, $minutes) { 
$data = Cache::find($key, $minutes); 
return $data; 
} 
private function find($key, $minutes){ 
if(Cache::has($key);){ 
return Cache::get($key); 
} 
// Database Server is called from the Cache Server. 
$DBdata = Database::find($key); 
Cache:put($key, $DBdata, $minutes); 
return $DBdata; 
}

Keširanje UI dela Laravel aplikacije

Keširanje UI-a vaše Laravel aplikacije je koncept poznat kao Full Page Cache (FPC). Pojam se odnosi na proces keširanja HTML odgovora iz aplikacije.

Odličan je za aplikacije gde se dinamički HTML podaci ne menjaju često. Možete keširati HTML odgovor za brži ukupni odgovor i renderovanje HTML-a.

FPC možemo implementirati sa sledećom linijom koda:

class ArticlesController extends Controller { 
public function index() { 
if ( Cache::has('articles_index') ) { 
return Cache::get('articles_index'); 
} else { 
$news = News::all(); 
$cachedData = view('articles.index')->with('articles', $news)->render(); 
Cache::put('articles_index', $cachedData); 
return $cachedData; 
  } 
 } 
}

Na prvi pogled, primetili ste da proveravamo da li stranica articles_index već postoji u našem keš serveru. Zatim vraćamo stranicu renderovanjem sa Laravelovim view() i render() metodama.

U suprotnom, renderujemo stranicu i čuvamo izlaz u našem keš serveru za sledeće zahteve pre nego što vratimo renderovanu stranicu pretraživaču.

Izrada Laravel aplikacije

Sada ćemo primeniti ono što smo naučili do sada tako što ćemo kreirati novi Laravel projekat i implementirati Laravel keš.

Ako niste koristili Laravel, možete pročitati šta je Laravel i pogledati našu listu Laravel tutorijala da biste počeli:

Popularni Laravel paketi za programere

Kako da instalirate Laravel 10.x-dev (dev)

Kako da optimizujete svoje Laravel aplikacije

Kako da koristite ugrađen Laravel-ov klijent za interakciju sa eksternim API-jima

Postavljanje Laravela

Prvo ćemo kreirati novu Laravel instancu koristeći sledeću komandu. Možete pogledati zvaničnu dokumentaciju za više informacija.

Otvorite konzolu i idite do mesta gde čuvate svoje PHP projekte pre pokretanja dole navedenih komandi. Pazite da imate pravilno konfigurisan i instaliran Composer.

composer create-project laravel/laravel fast-blog-app 
// Change directory to current Laravel installation 
cd fast-blog-app 
// Start Laravel development server. 
php artisan serve

Konfiguracija i popunjavanje baze podataka

Sada ćemo postaviti našu bazu podataka, kreirati novi Article model i popuniti 500 dummy (lažnih) podataka za testiranje.

Otvorite vaš klijent baze podataka i kreirajte novu bazu podataka. Mi ćemo isto to uraditi sa imenom fast_blog_app_db i zatim popuniti naš .env fajl sa kredencijalima baze podataka:

DB_CONNECTION=mysql 
DB_HOST=127.0.0.1 
DB_PORT=3306 
DB_DATABASE=fast_blog_app_db 
DB_USERNAME=//DB USERNAME HERE 
DB_PASSWORD=//DB PASSWORD HERE

Zatim ćemo pokrenuti sledeću komandu da bismo kreirali migraciju i Article model istovremeno:

php artisan make:model Article -m

Otvorite novu migraciju koja se nalazi u database/migrations/xxx-create-articles-xxx.php i nalepite sledeći kod:

<?php use Illuminate\Support\Facades\Schema; 
use Illuminate\Database\Schema\Blueprint; 
use Illuminate\Database\Migrations\Migration; 
class CreateArticlesTable extends Migration 
{ 
/** * Run the migrations. 
* 
* @return void 
*/ 
public function up() 
{ 
Schema::create('articles', function (Blueprint $table) { 
$table->id(); 
$table->string('title'); 
$table->text('description'); 
$table->timestamps(); 
}); 
} 
/** 
* Reverse the migrations. 
* 
* @return void 
*/ 
public function down() 
{ 
Schema::dropIfExists('articles'); 
 } 
}

Sada pokrenite komandu ispod da biste kreirali novi seeder.

php artisan make:seeder ArticleSeeder

Otvorite sada novi seeder fajl koji se nalazi u database/seeders/ArticleSeeder.php i nalepite sledeći kod:

<?php namespace Database\Seeders; 
use App\Models\Article; 
use Illuminate\Database\Seeder; 
class ArticleSeeder extends Seeder 
{ 
/** 
* Run the database seeds. 
* 
* @return void 
*/ 
public function run() 
{ 
Article::factory()->count(500)->create(); 
 } 
}

Otvorite DatabaseSeeder.php fajl u istom direktorijumu i dodajte sledeći kod:

<?php namespace Database\Seeders; 
use Illuminate\Database\Seeder; 
class DatabaseSeeder extends Seeder 
{ 
/** 
* Seed the application's database. 
* 
* @return void 
*/ 
public function run() 
{ 
$this->call(ArticleSeeder::class); 
 } 
}

Sada pokrenite komandu ispod da biste kreirali novi factory

php artisan make:factory ArticleFactory

Otvorite novo napravljen factory koji ste pronašli u database/factories/ArticleFactory.php i zalepite sledeći kod:

<?php namespace Database\Factories; 
use App\Models\Article; 
use Illuminate\Database\Eloquent\Factories\Factory; 
class ArticleFactory extends Factory 
{ 
/** 
* The name of the factory's corresponding model. 
* 
* @var string 
*/ 
protected $model = Article::class; 
/** 
* Define the model's default state. 
* 
* @return array 
*/ 
public function definition() 
{ 
return 
[ 'title' => $this->faker->text(), 
'description' => $this->faker->paragraph(20) 
  ]; 
 } 
}

Zatim pokrenite sledeću komandu da biste migrirali našu novokreiranu šemu i takođe popunili naše lažne podatke za testiranje:

php artisan migrate --seed

Kreiranje article controller-a

Zatim ćemo kreirati naš kontroler i postaviti naše rute da obrade naš zahtev i preuzmu podatke koristeći gore navedeni model.

Pokrenite sledeću komandu da biste kreirali novi ArticlesController unutar foldera app/Http/Controllers:

php artisan make:controller ArticlesController --resource

Otvorite fajl i dodajte sledeći kod u klasu:

// Returns all 500 articles with Caching 
public function index() { 
return Cache::remember('articles', 60, function () { 
return Article::all(); 
}); 
} 
// Returns all 500 without Caching  
public function allWithoutCache() { 
return Article::all(); 
}

Nakon toga, otvorite api.php fajl koji se nalazi unutar routes/ foldera i nalepite sledeći kod da biste kreirali endpoint koji možemo pozvati da bismo preuzeli naše podatke:

Route::get('/articles', 'ArticlesController@index'); 
Route::get('/articles/withoutcache', 'ArticlesController@allWithoutcache');

Testiranje performansi

Na kraju, testiraćemo performanse odgovora naše aplikacije sa ili bez implementacije Laravel keša.

Slika ispod prikazuje vreme odgovora API-ja sa implementiranim kešom:

A screenshot of the Laravel API response time with cache implemented.

Sledeća slika prikazuje vreme odgovora API-ja bez implementiranog keša — obratite pažnju da se vreme odgovora povećalo za preko 5.000% u odnosu na keširanu instancu:

A screenshot of the Laravel API response time without cache implemented.

Zaključak

Prikazali smo različite strategije za implementaciju i manipulaciju Laravel keširanjem, izradom novog projekta, testiranjem njegovih odgovora i na kraju i upoređivanjem rezultata.

Takođe ste naučili kako koristiti različite drajvere i metode Laravel keširanja.

Pored toga, implementirali smo različite strategije keširanja kako bismo vam pomogli da odlučite koja bi najviše odgovarala vašem sledećem Laravel projektu.

Da li ste do sada koristili laravel keširanje u nekom projektu? Pišite nam u komentarima o svojim iskustvima.

Slični postovi:

Bez komentara

Оставите одговор

Ваша адреса е-поште неће бити објављена. Неопходна поља су означена *