Önbellek

1.7k görüntülenme Markdown

Dosya tabanlı bir önbellek, bilinmeye değer tek bir metot, sessizce kırılması kolay bir üretici sözleşmesi ve içine asla girmemesi gereken şeylerin kısa listesi.

Genel Bakış

Herkes için aynı olan tekrarlı okumalar önbelleklenir: bir katalog, bir menü ağacı, bir fiyat tablosu. Kayıtlar depolar halinde gruplanır, depo başına bir dosya tutulur ve hepsine tek bir okuma-geçişli çağrıyla erişilir.

Kurulum genelindeki önbellek anahtarı o çağrının içinde dikkate alınır; yani önbellek kapalıyken üretici her istekte çalışır. Çağırmadan önce anahtarı kendiniz kontrol etmeyin.

Referans

Cache
public static function remember(string $name, string $key, int $ttl, callable $producer);
public static function getInstance(): self;

// $config: string verilirse depo adıdır, dizi verilirse 'name', 'path', 'extension' kabul eder.
public function __construct($config = []);

public function store($key, $data, $expiration = 86400): bool;
public function retrieve($key, $timestamp = false);
public function isCached($key): bool;
public function erase($key): self;
public function eraseExpired(): int;
public function eraseAll(): self;
public function clear($keys = []): void;
Cache::remember() İstediğiniz metot. Saklanan değeri döndürür ya da üreticiyi çağırır, sonucunu $ttl saniye boyunca saklar ve onu döndürür.
Cache::getInstance() Aşağıdaki çağrılar için paylaşılan örnek. new ile bir örnek kurmak paylaşılan örneği de değiştirir; kabul edilmiş bir davranıştır ama bilinmesi gerekir.
store() Tek bir kaydı yazar. Değer serialize edilir ve 0 verilen $expiration hiç sona ermez demektir. Lisans alan adı host ile eşleşmezse false döner.
retrieve() Tek bir kaydı okur; yoksa ya da okunamıyorsa null döner. İkinci argüman değer yerine yazılma zamanını ister ama o alan serialize edilmeden saklandığı için false döner, üzerine bir şey kurmayın.
erase() Geçerli depodan tek bir kaydı siler. Depo varken anahtar yoksa exception fırlatır; isCached() ile koruyun ya da yakalayın.
eraseAll() Geçerli deponun dosyasını olduğu gibi siler, içindeki her kaydı.
clear() Depoları toptan boşaltır. Argüman depo adları listesidir ya da virgülle ayrılmış bir dizedir; argümansız çağrıldığında bütün depo dosyalarını siler.

Depo, Anahtar, Ömür

ArgümanNeyi adlandırırNeye dönüşür
$nameDepoStorage önbellek dizini altında tek bir dosya: <ad>.cache. Küçük harfe çevrilir; harf, rakam, nokta, alt çizgi ve tire dışındaki her şey atılır.
$keyO deponun içindeki tek bir kayıtDosyadaki bir dizi anahtarı; serialize edilmiş değeri, yazılma zamanını ve ömrünü birlikte tutar.
$ttlSaniye cinsinden ömürBir saat için 3600, statik referans verisinde bir gün için 86400, hiç sona ermemesi için 0.

Üretici Ne Döndürmeli

serialize() işleminden geçip aynı şekilde geri gelen her şey: dizi, dize, sayı, düz nesne. Closure, resource ve açık bağlantılar gelmez. Closure'a dönüş tipini yazın; böylece yanlış biçim okunduğu yerde değil yazıldığı yerde patlar.

üretici biçimleri
// Uygun: bir dizi, ve tip de bunu söylüyor.
Cache::remember('website', 'tld_requirements', 3600, fn (): array => self::build_requirements());

// Uygun: render edilmiş bir dize.
Cache::remember('website', 'sitemap_' . $lang, 3600, fn (): string => $this->build($lang));

// Uygun: birden çok yakalanan değer, bloklu gövde.
Cache::remember('website', 'plans_' . $categoryId . '_' . $ucid, 3600, function () use ($categoryId, $ucid): array {
    $rows = self::plans($categoryId);

    return self::decorate($rows, $ucid);
});

// Bozuk: null yazılır ama "yok" olarak geri okunur; üretici sonsuza kadar her
// istekte çalışır ve önbellek sessizce hiçbir şey yapmaz.
Cache::remember('website', 'maybe_nothing', 3600, fn () => null);

Anahtarda Ne Olmalı

Önbelleklenmiş değer, aynı anahtarı hesaplayan herkes tarafından paylaşılır; dolayısıyla anahtar, değerin bağlı olduğu her şeyi adlandırmalıdır.

Değer şuna bağlıysaAnahtar şunu taşımalıTipik parça
Para ya da biçimlendirmeHizmet edilen para birimiMoney::selected()
Herhangi bir metin ya da bağlantıAktif dilLanguage::selected()
Bir kayıt, kategori ya da filtreO kimlik$categoryId
Giriş yapmış ziyaretçiHiçbir şey, çünkü önbelleklenmemeliGeçerli değil

Örnek

okuma tarafı
static function catalog_plans(int $categoryId, string $type, string $layout = 'grid'): array
{
    $ucid = Money::selected();

    // Fiyatlar para birimine, etiketler dile bağlı; anahtar ikisini de taşıyor,
    // ayrıca satırları seçen her şeyi.
    $plans = Cache::remember('website', 'plans_' . $categoryId . '_' . $type . '_' . $layout . '_' . $ucid . '_' . Language::selected(), 3600,
        fn (): array => self::catalog_plans_fresh($categoryId, $type, $layout, $ucid));

    // Stok her siparişle değişir; bu yüzden önbelleğin parçası olmaz, önbellekten
    // gelen yükün üzerine canlı tazelenir.
    if ($plans) {
        $stocks = self::catalog_stocks(array_map(fn ($p) => (int) $p["id"], $plans));
        foreach ($plans as &$plan) {
            $stock = trim((string) ($stocks[(int) $plan["id"]] ?? ''));
            $plan["in_stock"] = ($stock === '' || (int) $stock > 0);
        }
        unset($plan);
    }

    // Kancalar HER istekte çalışmalıdır, bu yüzden üreticinin dışındadır. Bağlam
    // önce bir değişkene alınır: runRefs bütün argümanlarını referansla geçer.
    $ctx = ['category_id' => $categoryId, 'type' => $type, 'layout' => $layout];
    Hook::runRefs('filter:product.catalog_plans', $plans, $ctx);

    return $plans;
}
diğer taraf: değeri düzenleyen onu temizler
trait AdminManageWebsite
{
    public function save_menu_changes(Operation $operation): bool
    {
        $operation->demo();

        // ... satırları yaz ...

        // Hedefli: yalnız 'menus' deposu, depo adıyla adreslenir.
        Cache::getInstance()->clear(['menus']);

        return $operation->output(['status' => "successful"]);
    }
}

// Tek bir kaydı silmek diğer metottur ve bulamadığında fırlatır.
$cache = new Cache('website');
if ($cache->isCached('plans_5_hosting_grid_1_tr')) $cache->erase('plans_5_hosting_grid_1_tr');

Tuzaklar

clear() depoyu, erase() kaydı adlandırır

clear() metoduna bir kayıt anahtarı geçmek o kaydı silmez. Dizeyi depo adı sayar, yani büyük ihtimalle var olmayan bir dosyayı siler ve bayat kaydı olduğu yerde bırakır, üstelik hata da vermez. Tek kayıt için erase() kullanın ve anahtar yokken fırlattığını unutmayın.

Kimin sorduğuna bağlı hiçbir şeyi önbelleklemeyin

Stok, sepet, girişin arkasındaki her şey. Ziyaretçiye özel önbelleklenmiş bir değer sıradaki ziyaretçiye sunulur; bu bayat sayfa değil veri sızıntısıdır.

Kancaları üreticinin dışında tutun

Üreticinin içindeki bir kanca yalnız önbellek boşken ateşlenir; dinleyici kayıt soğukken çalışıyor görünür ve ömrün geri kalanında sessizce durur. Veriyi önbellekleyin, sonra dinleyicilerin onun üzerinde çalışmasına izin verin.

Bir şey onu geçersiz kılmalı

Operatör değeri bir ekrandan düzenleyebiliyorsa o ekran depoyu temizlemelidir. Düzenleme ekranı temizlemeyen yeni önbelleklenmiş veri, ömrü boyunca eski sürümü sunmaya devam eder ve size ulaşan şikayet önbellekle değil o ekranla ilgili olur.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.