Memcached verileri önbelleğe alma için tasarım deseni

4 Cevap php

Bu mevcut veritabanı sorgularını etrafında isteğe bağlı memcached önbelleğe sarmak kolay. Örneğin:

Eski (DB-only):

function getX
    x = get from db
    return x
end

Yeni (memcache ile DB):

function getX
    x = get from memcache
    if found
      return x
    endif

    x = get from db
    set x in memcache
    return x
end

Şey size önbelleğe istiyorum nasıl her zaman değil, olsa. Örneğin aşağıdaki iki sorgu alır:

-- get all items (recordset)
SELECT * FROM items;

-- get one item (record)
SELECT * FROM items WHERE pkid = 42;

Ben önbelleğe alma işlemek için yukarıdaki sözde kod kullanmak için olsaydı, ben iki öğenin 42 tüm alanları saklamak olacaktır. Bir kere büyük plak seti ve bir kez kendi kendine. Doğrusu böyle bir şey yapmak istiyorum oysa:

SELECT pkid FROM items;

ve PK adlı bu endeksi önbelleğe. Sonra da tek tek her kayıt önbelleğe.

Yani özet olarak, DB için en iyi çalışacak veri erişim stratejisi düzgünce memcache stratejisini uymuyor. Ben memcache katman ben tür iki dünyanın en iyi olmasını istiyorum (memcache aşağı ise yani, site hala çalışır) isteğe bağlı, ama bunu yapmak istiyorum çünkü, ben korumak gerekir eminim bir 2 farklı formlarda (.. ve 2 tek sorguda kayıt getirilemedi 1 kayıtları daha sonra, endeksi getirme) de sorguları çok. Bu pagination ile daha karmaşık alır. DB ile LİMİT / OFFSET SQL sorguları yapardım, ama memcache ile sadece PK adlı dizin getirme ve daha sonra dizinin ilgili dilim toplu olsun istiyorum.

Ben düzgünce bu tasarımı nasıl emin değilim, kimse herhangi bir öneriniz var mı?

Daha da iyisi, bu karşı kendinizi geldim eğer. Bunu nasıl ele?

4 Cevap

Bunun dışında en iyi şekilde, daha sonra bir önbellek kullanarak yapıyorsanız, veri her zaman bir ölçüde bayat olması ve verilerin bazı bölümleri birbirleri ile senkronize olacağını olacağını kabul etmek zorunda. Tek bir kopya sürdürerek bugüne kadar tüm kayıtları tutmaya çalışıyorum iyi ilişkisel veritabanları için sol bir şeydir, bu nedenle bu muhtemelen RAM çok güçlü bir 64-bit DB sunucusu ile daha iyi zaman gereken davranış olup olmadığını bu yüzden kendi iç önbelleğe alma gerçekleştirebilirsiniz.

Eğer eski verileri (gerçek ölçeklenebilirlik önemli ise gerekir ki) kabul edebilir, o bir yaklaşım sadece önbelleğe ayarlamak tüm sonuç atmak için; çoğaltılması konusunda endişelenmeyin. RAM ucuz. Eğer önbellek dolu oluyor bulursanız o zaman sadece daha fazla RAM ve / veya önbellek sunucularını satın. Eğer koşullar X ile filtrelenmiş bir dizi öğeleri 1-24 temsil eder ve aynı arama için sorulduğunda Y daha sonra tüm bu bilgileri içeren bir önbellek tuşunu kullanın, ve bir sorgu varsa Örneğin yine sadece kümesi tüm sonucu dönmek önbellek. Siz bir vuruşta önbellek tam sonuç kümesi olsun, ya sen veritabanına gidin.

Zor şey veri bayat olabilir ne kadar çalışıyor ve ne kadar bayat böyle asgari güncelleme aralıklarında olarak iş gereksinimlerini (a) insanlar çok fazla fark, veya (b) kırılma ya olmadan olabilir edilir.

Bu yaklaşım, salt çoğunlukla uygulamalar, sorguları ve / veya veri filtre kriterleri bir sonlu kümesini disk belleği var, özellikle olanlar için iyi çalışır. Ayrıca uygulama sadece önbelleği kapalı% 0 isabet oranı ile, açık veya kapalı önbellek ile tam olarak aynı çalışır anlamına gelir. Bu hemen hemen tüm vakalarda blinkBox de almak yaklaşımdır.

Identity Map deseni hakkında okuyun. Bu, sadece uygulama alanında belirli bir satırın bir kopyasını tutmak emin olmak için bir yoldur. Eğer memcached ya da sadece düz nesneleri saklamak ister, bu ne istediğinizi işlemek için bir yoldur. Ben genellikle bir anda bir satır getir zaman Kimlik Harita iyi kullanıldığını tahmin ediyorum.

Bir tablonun bütün alt kümelerini getir, o zaman tek tek her satır işlemek zorunda. Lütfen satır% 99 önbellek vardır ama bir veritabanından getiriliyor isterse, (zaten SQL sorgusu çalıştırmak zorunda, çünkü sık sık, sizin önbellek dışında en iyi şekilde alıyoruz olsun ikilem olabilir en azından bir defa).

Siz önbellek değil sadece satırları almak için SQL sorgusu dönüştürmek olabilir, ama SQL sorgu daha pahalı yapmadan otomatik olarak bu dönüşümü gerçekleştirmek için nontrivial bulunuyor.

Eh, ben sizinle yaşamak zorunda olacak bir şey sanırım. Eğer gerçekten toplu şeyler yapmazsak Memcahced iyi çalışacaktır. Örneğin bu gibi şeyler için harika "Bu kullanıcı için işler nerede? İşte bu kullanıcı için bir sürü şey olduğunu." Bu gerçekten bu sorgu partiler yapmaz anlamına gelmez. Tabii ki olacak - kullanıcı bazı şeyler onun / mesaj gibi şeyler ise.

Sana sahip olacağım sorun kendi DB bir öğeyi almak gerekiyor sorguları ve önceki öğeler aynı tür demet almak bazı karıştırma durumlarda sanırım.

Duruma bir kapak tarafı her zaman vardır. Eğer gerçekten uygulanması ile kıllı almak istiyorsanız çok çirkin memcached.Very zaten mevcut öğeleri içermez için toplu sorguları değiştirebilirsiniz ...

Bence o zaman aşağı gelir "sorguları really önbelleğe I istiyorsun hangi?"

EDIT:

Ben bu konuda gitmek yoludur:

  • Tek öğesi sorgusu - memcached yılında, o birini kullanın, aksi takdirde DB ve güncelleme memcached alınamayacak.
  • Toplu sorgu - sadece her şeyi ve güncelleme memcached olsun, ürün memcached içinde olduğu konusunda endişelenmeyin.

Tabii bu toplu sorguları zaten tamamlamak için cehennem çok daha fazla zaman alır ve bu yüzden ben zaten zaten önbelleğe alınmış öğeleri için ben dış aramaları ile yaşamak çok fazla zaman harcıyorum varsayar.

Eğer toplu bir çok sorgular kullanmak Ancak, sonunda, sizin önbellek öğeleri bir sürü içerecektir. Bu nedenle Eğer hala veritabanı aramaları gerçekleştirmek istediğiniz hangi noktada belirlemek için denge gerekir. İyi bir şey toplu sorgu önceki uygulamaların yaşam döngüsü içinde ise, o zaman her şey daha önce önbelleğe alınmış olacaktır olduğunu. Ilk toplu sorgu sonra önbellek veri güncelleştirmeleri veya silmeleri tarafından geçersiz sürece artık DB getirmesi gerekmez kendin söyle olabilir.

İşte NHibernate (ve bu nedenle muhtemelen Hazırda) bunu nasıl benim anlayış. Bu 4 önbelleklerini vardır:

  • satır cache: Bu DB satır önbelleğe alır. Önbellek anahtar diğer girdileri satır değerleri, TabloAdı # id.
  • sorgu önbellek: Bu sonuçlar, belirli bir sorgu için döndü önbelleğe alır. Önbellek anahtar parametreleri ile sorgu, veri sorgu sonucu olarak iade edildi TableName # id satır anahtarlarının bir listesi.
  • koleksiyonları cache: Bu (. NHibernate tembel-yüklü olmasını sağlar) herhangi bir ebeveyn çocuk nesneleri önbelleğe Yani myCompany.Employees erişmek ise, çalışanların toplama koleksiyonları önbelleğinde önbelleğe alınır. Önbellek anahtar veri çocuğun satırlar için TableName # id satır anahtarlarının bir listesi ToplamaAdı # entityid vardır.
  • tablo güncelleme cache: Her tablonun bir listesini ve ne zaman son güncelleme oldu. Verileri önbelleğe sonra bir tablo güncellendi ise, veri bayat kabul edilir.

Bu, oldukça esnek bir çözümdür çok verimli bir alan-bilge ve veri bayat olmayacağını garanti eder. Dezavantajı önbellek sunucusu ağda ise bir tek sorgu bir sorun olabilir önbellek birkaç gidiş-gelişleri, ihtiyaç olabilir.