Nedir bayat önbelleğe değerleri önlemek için (memcache) anahtarlarını yönetmek için en iyi yolu nedir?

5 Cevap php

Ive son zamanlarda ağır mysql yük (bunu yapabilir olduğunca optimize mysql idi) altında olmuştur sitemde memcache uygulanmaktadır. Hepsi benim yük sorunları çözülmüş ve site güzel çalışıyor.

Im şimdi karşı karşıya sorun bayat önbelleğe alınmış değerlerdir. Ben en sayfalarında 1saat otomatik son kullanma süreleri var, ve Im de anahtarı silerken DB chnages değer, ama ben zorluk takip ve verimli bir şekilde tüm anahtarlarını temizleyerek sahip.

Bazı sayfalarda, onun önemsiz. Ben (item_4653 örneğin) anahtar item_id olarak yapabilirsiniz ve bunun için veri güncellenir, veya öğe silindiğinde, anahtar temizlenmektedir.

Ama çoğu sayfalarında, ben, md5 bunu komut dosyası dosya adını + sorgu dizesi alır ve memcache anahtar olarak kullanan. Bu, (çok yaygındır), karmaşık URL'ler için özellikle yararlıdır.

Örneğin ben şu sayfa yüklendi var.

index.php? search_keywords = good & search_section = 1 & sort = bırakma & page = 2

Bu memcache getirilecek öğelerin bir listesini içerecektir. Başka bir kullanıcı daha sonra, orada görünmez dışında "good" başlığında, ve, 2. sayfada görünür değerlerin aralığında olur bir item, gönderilinceye kadar önbellek yenilenir. Ne yapar bu daha karmaşık, yeni eklenen öğe benzersiz olacak ayrıca sort = yeni? Index.php görünür, hem de bu vb index.php? Kategori = some_category? Page = 1 ve Her 1 olmasıdır tuşu (script adı + sorgu dizesi md5).

Onlar canlı DB getirilen olsaydı Yani yeni eklenen madde, sayfaları onlarca görünebilir, ama bayat önbelleği güncellenir kadar alışkanlık onlara herhangi görülebilir. Tek seçenek öğe otomatik olarak sona erecek için beklemektir.

Bu sorun, değerlerin tüm olası önbelleğe alınmış sayfa kombinasyonları için, talep üzerine haberdar olmak için VAR (özel kodlu) benim forum, hatta daha belirgin hale gelir. Ben 4 sayfa konu var, ve ben sayfa 2 3 spam mesaj fark diyelim. Onları sildikten sonra, sayfa 2 yeniden, ama sonra o da sayfa 3 ve 4'ü yeniden inşa etmek için var, aksi takdirde yeni sayfa 2 yeniden yinelenen mesaj olacak ve eski sayfa 3. Thats sadece 1 örnek ..... bu senaryoların düzinelerce vardır için.

Herhangi bir fikir?

5 Cevap

Eğer memcached içinde tüm sayfaları önbelleğe olduğundan, sayfalarınızı birbirleri ile veritabanından önbelleğe veri paylaşımı olamaz. Ben memcached anahtar olarak page1 ve page2 ile, sayfa1.php ve sayfa2.php söylüyorlar. Iki sayfa görüntülemek items. Ben yeni bir öğe eklemek. Şimdi page1 ve page2 sona zorunda.

Bunun yerine, ben memcached bir items tuşuna, o sayfa1.php ve öğeleri görüntülemek için sayfa2.php hem kullanımı olabilir. Ben yeni bir öğe eklediğinizde, ben items tuşuna (ya da daha iyisi, o değerini güncellemek) sona erecek ve sayfa1.php ve sayfa2.php hem up-to-date.

Hala tüm sayfayı önbelleğe almak istiyorsanız, değişecek emin veri önbelleğe değişiklikleri olma (veri çok sık değiştiriyorsa, bu mantıklı olmaz). Anahtarlarını bilgi ekleyebilir Örneğin:

"page1:[timestamp of newest item]"

Bu şekilde yeni öğe, ucuz bir sorgu damgası bakmak ve onunla önbellek anahtarı oluşturabilirsiniz. Yeni bir madde ilave edildiğinde, önbellek anahtar otomatik olarak sona erecek, değişecektir. Bu yöntem hala yeni öğenin zaman damgası, her zaman, ne olduğunu görmek için veritabanı vurmak zorunda kalıyoruz.

Size memcached tuşları için basit bir adlandırma düzeni yararlanabilir - bu yüzden silmek kolaydır. MD5 çözelti ile, genellikle aynı verileri göstermek şeyler için çok sayıda anahtar yaratmak olabilir gibi görünüyor.

Ayrıca 20 dakika gibi kısa bir önbellek zaman düşünebilirsiniz?

Ayrıca - bu arama sonuç sayfalarında her biri için kaç sayfa başına ürün alınıyor? Eğer bir paginated arama varsa - sunucudan 50 ürün almak çok yoğun olmamalıdır.

(Kullanışlı bir dizine ekleyerek) Eğer mysql sunucu ayarlanmış olabilir, ancak (EXPLAIN çıkışını inceleyerek onları iyileştirmek) sorguları ayarlı, ya da tablo yapıları?

Ben de bu sayfalarda sorguları nasıl yoğun merak ediyorum. Birkaç tablo katılmak mı? Ya da birkaç sorguları (aşağıda özetlenmiştir) - Sen basit bir sorgu yapıyor yararlanabilir.

Alternatif - ya da birkaç - sonuç her satır için, başka bir sorgu çalıştırmak mı? Eğer iç içe geçmiş sorguları yapmak zorunda önler biraz daha karmaşık bir arama sorgusu yararlanabilir. Veya, aynı şeyi yapar bir ORM kütüphane tarafından ısırılan edilir, her tekrarında alt öğeler için sorgular, sonra bir arama çalışır?

'Birkaç basit sorguları' çözümü - Bir öğe var ise, ve bu set sonuç kategori bilmek istiyorum ... - örneğin söylemek

Bu yerine:

SELECT i.id, i.name,
c.category FROM items AS i
INNER JOIN categories AS c
ON i.category_id = c.id;

Bu basit bir örnek - ama kategoriler vardı demek, ve birkaç diğer Joın çıkıyor.

Bu yol gidebilir:

// run this query
SELECT id, category FROM categories - and put that into a keyed array.

// then in PHP create an array keyed by the id
$categories = array();

while ( false !== ( $row = mysql_fetch_assoc ( $result ) ) ) 
{
  $categories[ $row['id'] ] = $row['category'];
}

// and so on
$types = array(); // ...
// etc.

Sonra sadece senin nerede hükümler ve çıkış ile öğeleri tablo, aramanızı ama KATILDI tüm olmadan yapmak demek ...

<?php foreach($items as $item): ?>
  <h4><?php echo $item['name']; ?></h4>
  <p>Category:  <?php echo $categories[ $item['category_id'] ]; ?></p>
  <p>Type:  <?php echo $types[ $item['type_id'] ]; ?></p>
  <!-- and so on -->
<?php endforeach; ?>

Biraz getto, ama belki de bu - ve diğer öneriler - yardımcı olacaktır.

Memcached :: seti dolacak parametresi vardır. Belki bir saat, bu varsayılan sağlayabilirsiniz, ancak arama sonuçlarını döndürmek sayfaları için - ya da forumda, bir zaman kısa bir süre için bu ayarlayabilirsiniz.

Yapabileceğiniz kaç basit şeyler:

Eğer gerçekten bir önbellek anahtarının olarak sorgu dizesi kullanmak istiyorsanız Birincisi, daha deterministik ve öngörülebilir hale. Ben sorgu dizesi, örneğin sıralayarak bu yapardım: ?zed=7&alpha=1 dönüşür ?alpha=1&zed=7. Ayrıca önbelleğe alma tuşu alakalı olmayan değişkenleri şerit.

? Sayfa parametresinin sorunu işlemek, ve önbellek yenilenir değil çünkü ürün gösterilmesini değil, ben bir kaç fikir var:

Önbellek anahtarının bir 'versiyonu' ekleyerek Folke'nin fikri iyi çalışır. Aynı hile kolayca edilmemiş gibi bağlantı yapmak için kullanılır.

Başka bir yaklaşım önbellek değeri sayfaların sayısını saklamak için, ve veritabanı güncellenir zaman sonra, önbellek tuşları ile yineleme olur.

cache.put("keyword,page=3", array(num_pages=7, value=...))

...later...
update_entry()
num_pages, value = cache.get("keyword,page=3")
for i in num_pages:
  cache.flush("keyword,page="+i)

Bu iyi bir fikir olup olmadığını orada kaç sayfa bağlıdır, ve döngü çalışırken gelen güncellemeleri şans.

Üçüncü bir fikir tüm sonuç yerine sonuçlarının sadece o sayfanın ayarlamak önbelleğe almaktır. Bu, ya da sonuç kümesinin boyutuna kadar bağlı bir seçenek olmayabilir. Bu sonuç kümesi güncellenir, sadece o anahtar kelime için önbelleği temizleyin.

cache.put("keyword", array(0="bla", 1=foo", ...)
...later...
cache.get("keyword")[page_num]

Dördüncü fikir önbelleğe alma arkaplana değiştirmek ve bu durumun üstesinden gelmek için yerleşik bir şey kullanmaktır. Ben orada ne diğer önbellek sunucuları bilmiyorum, bu yüzden etrafına bakmak gerekir.

Son olarak, tüm bu ek, denemek ve önbellek girişleri sona zaman hakkında daha akıllı olabilir. örneğin, güncellemeleri ya da anahtar kelime, vb saniyede sorgu sayısı arasındaki ortalama zaman kullanabilirsiniz

Eğer önbellek kodunuz için birçok değişiklik yapmadan her zaman güncel olduğundan emin olmak için yapabileceği ne bir "versiyonu önbellek" ile çalışmak olduğunu. Bu yapacaktır memcache isteklerinin sayısını artırmak, ama bu sizin için bir çözüm olabilir.

Bu çözüm ile ilgili bir diğer iyi şey sona asla sona erme süresi olabilir.

Fikir temelde durumda (Keywork başına değil kombinasyonu) belirli bir anahtar kelime içinde memcache için saklanan bir sürüm numarasına sahip olmaktır. Bu nasıl kullanılır?

Birisi yeni bir öğe gönderdiğinde:

  • başlığında her kelime için, do if(!Memcache:increment("version_" + keyword)) {Memcache:set("version_" + keyword);}

Birisi bir sorgu çalıştırıldığında:

  • senin yapıyorsun md5 şey zaten ok. Ayrıca size memcache anahtar için arama dizesi her anahtar kelimenin bir sürümünü eklemek gerekir.

Bu kısa sürede bir anahtar kelime yeni sonuçlar (veya silerken daha az) olduğu gibi, sürüm çarptın olmasını sağlar ve bu ilgili tüm memcache sorgular gibi.

Önbellek her zaman güncel ve sorguları kadar potansiyel önbellek 1 saatten daha uzun kalmak olabilir.