A HTML / PHP Cache uygulamak için nasıl

4 Cevap php

Ben dahil bu bir, bir php önbellek sistemi (benim site özel kodlu, oldukça ağır sorgu ve büyüyen) uygulanması üzerinde çeşitli kılavuzları okudum: http://www.snipe.net/2009/03/quick-and-dirty-php-caching/

Bunu yaparken hakkında gitmek için en iyi yolu nedir, ben onları tamamen anlıyorum ama ben önbellekleyemez sayfanın belirli parçaları vardır?

4 Cevap

Eğer okur bir sürü yapmak ama nadiren güncellemek eğer önbelleğe yararlıdır. daha sık veritabanı değişiklikleri veriler, daha sorunlu bir önbelleğe alma sistemidir olur. önbelleğe alma işlemek için bir ağrı olabilir, sizin kod temeli belli bir karmaşıklık eklese. ve hatta en kötü durumda sitenizi yavaşlatabilir.

the most important question is:
when do you have to invalidate your cache? when does it become stale? in most of the cases, if the database-query returns different rows than at the time you cached that page. but how do you know that? you don't (maybe there is a way, but i can't think of any atm), because to check that, you probably have to query the result to compare.

ne yapabilirim:

  1. clear all your cache everytime the relevant parts of the database are updated
    this is indeed possible if your database only rarely gets updated - hourly, daily, weekly. but it's useless if changes are coming in continually. that's the case with most web projects.

  2. clear cached items after something happens
    this only works if changes do not have to be reflected instantly (e.g. doesn't matter if there's incorrect data for some time). in this case you simply could clear the cache for a certain item if it's older than X minutes, or more than Y pageviews happened.

  3. clear only the relevant pieces
    here you have to figure out which parts of the cache are affected when you're updating the database. if done right, changes are reflected instantly while performance improves.

en likley seçenek 3: Eğer öğrenmek zorunda. yani, bir örnek olarak, bir frontpage, arşiv sayfaları ve her giriş için bir ayrıntı sayfası oluşan bir web günlüğü klasik davayı almak sağlar.

admin panelinden (girdileri için rezil) ve yorumlar: değişiklikler ile tanıtıldı

bir giriş düzenlendi veya silindi alırsa, sizin için önbelleği temizlemek zorunda:

  • frontpage, giriş yeni ise
  • ilgili arşiv sayfası, giriş eski olsaydı
  • giriş için detay sayfası

Birisi commentes eğer sadece yorumların sayısı dizin veya arşivde görüntülenmeyen yalnızca detay sayfası temizlemek zorunda, ama. Aksi takdirde, giriş rezil aynı.

bir şey site genelinde değiştirilirse, tüm önbellek temizlenmiş olması gerekir (olmasa da)

Şimdi, giriş rezil ve arşivi düşünmek sağlar. arşiv tipi "Ayda bir sayfa" arasında ise, o zaman giriş aittir ay temizleyin. arşiv tür giriş 1-10, 11-20, 21-30, ama eğer ... en likley tüm arşiv-önbellek yeniden gerekir.

ve böylece ...

some of the problems:

  • Eğer doğru tüm etkilenen parçaları tespit yoksa, bu bayat veri ve / veya (un-) ölü bağlantıları yol açabilir.

  • güncellemeler çok sık gerçekleşmesi halinde bir sonraki sayfa gösterimi ne zaman olur, önbellek muhtemelen bayat yine ve yine yeniden gerektiğinden, önbelleği bina, ek eseridir.

  • Sayfanın bazı kısımları önbelleğe alma için uygun olmayan, örneğin (özel) arama fonksiyonu. önbellek başka yerde çalışır eğer her şey hızlı ve büyük, ama arama hala çok yavaş.

  • Eğer istekleri çok oluyor ise tüm önbelleğini temizlemek zorunda eğer sorunlu olabilir. Bir önbellek-miss normalde sayfa ilk etapta önbelleğe değilse daha pahalı çünkü o, sunucu boğabilirsin. 3 istek geliyor, ve diğer iki işlenir önce ilk istek sayfayı önbelleğe eğer daha da kötüsü, önbellek kez 3 kez yerine istedi alır.

benim tavsiyem:

  • veritabanı optimize. tuşları ve yapılandırma tamam mı? belki önbelleğe alma olmadan çalışır.

  • sorguları optimize. "Select açıklamak"!

  • sayfanın sadece önbellek parçaları - pahalı olanlar. str_replace ve tutucular ile küçük, ucuz değişiklikler doldurun

  • herşey doğruysa, apc kullanın veya dosyaları (genellikle büyük iş, ama apc / MEMC daha hızlı) yerine dosyaların memcached. ayrıca veritabanı önbellek için veritabanını kullanabilirsiniz, sık sık bu harika çalışıyor!

  • Eğer bir tembel veya istekli önbellek sistemi inşa ediyoruz? tembel anlamı: önbellek oluşturmak zaman sayfanın ilk talep, istekli anlamı: sağ güncellemeden sonra.

meh, ben sizin için gerçek bir tavsiye yoktur. sorun üzerinde çok fazla bağlıdır :)

update

anahtar 256 ile blog giriş yapmak için bir istek gidecekseniz. bunun blog girişini, yorum ve kim o giriş ve yorumlar sorgulamak ve tüm metin ve her şeyi biçimlendirmek için pahalı içeri anda oturum açmış gösteriyor. Şu anda oturum açmış kullanıcının oturumda bulunur.

İlk, sen önbelleğe istediğiniz bölümü için benzersiz bir anahtar oluşturun. Bu durumda, önbellek anahtar muhtemelen (bazı önek ve postfix ile) giriş veritabanı kimliği.

bu nedenle, önbelleğe alınmış dosya adı cache/blogentry_256.tmp olmalıdır. kontrol, bu dosya varsa.

  1. o yoksa, tüm pahalı sorgulama ve biçimlendirme yapmak geçerli kullanıcı adı olması ve cache/blogentry_256.tmp için sonucu kaydetmek gereken bir yer tutucu (örneğin {username}) bırakın. her istek üzerine herkes ya da değişiklikler için görüntülenen olmamalıdır bu dosyaya herhangi bir veri yazmak için değil dikkatli olun.

  2. Şimdi, dosyayı okumak (ya da 1'den verileri yeniden) ve yer tutucuya adı str_replace. echo sonucudur.

bir giriş değişmiş olur ya da birisi comments varsa, girdileri kimliği ile önbellek dosyasını silmeniz gerekir.

Bu tembel önbelleklemesidir - önbellek sadece kullanıcının isteği sayfa halinde inşa edilmiştir. dikkatli olun - bir açıklama içine bir kullanıcı türleri {username}, çok orada takılı eğer! anlamına gelir, sen str_replacing sonra önbelleğe alınan veriler ve Unescape onu kaçmak zorunda. Bu teknik çok memcached veya APC ile çalışır.

sorunlar: O önbelleğe alma kararı vereceklerinden etrafında tasarımı oluşturmak gerekiyor. örneğin yerine "yorumunu ekledi 6 Mayıs, 03:42" yorum "comment 5 dakika önce yayınlanmıştır" görüntülemek istiyorsanız, o zaman belada.

Neden bunları önbelleğe değil mi? Onlar çok hızlı değiştirmek çünkü ise, o zaman muhtemelen alma azaltmak için çalışıyor ve havai render daha iyiyiz.

Içeriği kullanıcıya göre değişir, o zaman kullanıcı başına farklı önbelleğe alınmış sürümlerini kadar sunabilir. Eğer bir nesne önbelleğini kullanıyorsanız, örneğin, daha sonra kullanıcının tanımlayıcı veya önbellek anahtarının bazı diğer benzersiz bir değer içerir. Böyle Squid gibi daha genel bir HTTP-seviyeli önbellek kullanıyorsanız, o zaman için, örneğin Vary başlığını ayarlayabilirsiniz Vary: Cookie, proxy, içeriği sunan kim çift kontrol etmek neden olacaktır.

Hala kamu önbelleklerini herhangi bir hassas bilgileri depolamak için değil önbelleklerini ve vekiller talimat olmalıdır.

Bu önbelleğe alma tek bir çözüm değil Unutmayın - Sizin uygulama değişkenleri kapsamına bağlı olarak, farklı düzeylerde önbelleğe sahip olabilir. Tek bir istek içinde, aynı veriler için ek sorguları önlemek için bir kimlik bir harita olabilir. Istekler arasında önbellek verilerine memcached kullanabilirsiniz. Veritabanı kendisi sorgu önbelleği, yanı sıra alt seviye önbellek diğer türleri vardır. Eğer önbelleğe ve bunun için bir strateji yapabilirsiniz anlamaya gerek tam sayfa, vb sayfanın tek tek parçaları - Sizin render motoru da farklı seviyelerde önbelleğe alabilir.

Ayrıca, tüm optimizasyon gibi, bir şey çimdik önce ölçmek emin olun. Bu 1) aslında yerine onları kötü ve 2) yerine başka bir şey daha, önemli şeyler odaklanmak yapmak yerine, bir şeyler geliştirmek sağlayacaktır.

İşte benim ipucu: adını dayalı bir "bölüm" önbelleğe sağlayan bir nesne veya işlev ya oluşturun. Eğer sayfanın bir bölümü önbelleğe ve bu şekilde bir if bloğu içinde işleme bölüm içerir. Ne yaptım karma gelen metin ve './cache' içinde dosya adı ve rejenerasyon olarak gerekli olup olmadığı boolean değerini döndü kullanılır; tabii ki bunun için çıktı tamponlamasını gerekir.

Bu size bir önbellek çerçeve verecek,

if(Cache::cached('index-recent-articles', 5 /* minutes */)) {
   Cache::start();
   echo 'stuff here';
   Cache::stop('index-recent-articles');
} // And if Cache::cached could echo the cached HTML when the result is false...
  // then this is a tidy else-less bit of code.

Bu optimal eğer ben memcache gibi sunucu tabanlı bir çözüm daha iyi olurdu, bilmiyorum, ama kavram size yardımcı olacaktır. Açıkçası önbelleği yönetmek nasıl, dosyaları veya veritabanı ya da uzantısı olsun, size kalmış.

Edit:

Eğer dosya tabanlı önbelleğe alma için isterseniz daha sonra bir sistem bu basit ihtiyacınız olabilir. Açıkçası ben senin yerinde test etmemiş, ve bu çoğunlukla sadece kafamın arkasından çekti, ama bu haliyle bu arzusu olabilir ne için iyi bir başlangıç ​​olduğunu.

abstract class Cache {
  const path = 'cache/';
  static function start()  { ob_start(); }
  static function end($id, $text = null) {
    $filename = sprintf('%s%u', Cache::path, crc32($id));
    file_put_contents($filename, $text === null ? ob_get_clean() : $text);
  }
  static function cached($id, $minutes = 5) {
    $filename = sprintf('%s%u', Cache::path, crc32($id));
    $time = $minutes * 60;
    if(time() - filemtime($filename) > $time) {
      return true;
    } else {
      echo file_get_contents($filename);
      return false;
    }
  }
}