Önbelleğe alma çözümünüzü asla yazmayın

Veritabanıyla çalışmayı hızlandırmanın bir başka yolu da, daha önce talep ettiğimiz nesneleri önbelleğe almaktır.

Önemli! Asla kendi önbelleğe alma çözümünüzü yazmayın. Bu görevin hiç hayal etmediğiniz pek çok tuzağı var.

Sorun 1 - önbellek temizleme . Bazen olaylar, bir nesnenin önbellekten kaldırılması veya önbellekte güncellenmesi gerektiğinde gerçekleşir. Bunu yetkin bir şekilde yapmanın tek yolu, tüm istekleri önbellek motoru aracılığıyla veritabanına iletmektir. Aksi takdirde, her seferinde önbelleğe içindeki hangi nesnelerin silinmesi veya güncellenmesi gerektiğini açıkça söylemeniz gerekecektir.

Sorun 2 - hafıza eksikliği . Önbelleğe alma, bellekteki nesnelerin çok yer kapladığını bulana kadar harika bir fikir gibi görünüyor. Sunucu uygulama önbelleğinin etkili bir şekilde çalışması için ek onlarca gigabayt belleğe ihtiyacınız var.

Ve her zaman bir bellek kıtlığı olduğundan, önbellekten nesneleri silmek için etkili bir strateji gereklidir. Bu, Java'daki çöp toplayıcıya biraz benzer. Ve hatırladığınız gibi, onlarca yıldır en iyi beyinler nesneleri kuşaklara göre işaretlemenin çeşitli yollarını icat ettiler, vb.

Problem 3 - farklı stratejiler . Uygulamada görüldüğü gibi, farklı nesneler için önbellekte depolama ve güncelleme için farklı stratejiler etkilidir. Verimli bir önbelleğe alma sistemi, tüm nesneler için tek bir strateji uygulayamaz.

Sorun 4 - . Nesneleri yalnızca önbellekte depolayamazsınız. Nesneler çok sık olarak diğer nesnelere referanslar içerir, vb. Bu hızla giderseniz, bir çöp toplayıcıya ihtiyacınız olmayacak: yalnızca kaldırılacak hiçbir şeyi olmayacak.

Bu nedenle, nesnelerin kendilerini depolamak yerine, bazen ilkel alanlarının değerlerini depolamak çok daha verimli olur. Ve bunlara dayalı olarak hızlı bir şekilde nesneler oluşturmak için sistemler.

Sonuç olarak, bellekte hızlı çalışması ve çok az bellek tüketmesi gereken tam bir sanal DBMS elde edeceksiniz.

Veritabanı önbelleğe alma

Doğrudan bir Java programında önbelleğe almaya ek olarak, önbelleğe alma genellikle doğrudan veritabanında düzenlenir.

Dört büyük yaklaşım vardır:

İlk yaklaşım, veritabanını denormalize etmektir . SQL sunucusu, verileri bellekte tablolarda depolanma biçiminden farklı şekilde depolar.

Veriler tablolarda diskte depolandığında, geliştiriciler genellikle veri tekrarını mümkün olduğunca önlemeye çalışır - bu işleme veritabanı normalleştirmesi denir. Böylece, bellekteki verilerle çalışmayı hızlandırmak için ters işlem gerçekleştirilir - veritabanı normalleştirme. Bir dizi ilgili tablo zaten birleştirilmiş bir biçimde - büyük tablolar vb. Şeklinde - saklanabilir.

İkinci yaklaşım, sorgu önbelleğe almadır . Ve sorgu sonuçları.

DBMS, kendisine çok sık olarak aynı veya benzer isteklerin geldiğini görür. Ardından, bu istekleri ve yanıtlarını önbelleğe almaya başlar. Ancak aynı zamanda, veritabanında değişen satırların önbellekten zamanında kaldırıldığından emin olmanız gerekir.

Bu yaklaşım, sorguları analiz edebilen ve DBMS'nin bunları en iyi nasıl önbelleğe alacağını anlamasına yardımcı olan bir insanda çok etkili olabilir.

Üçüncü yaklaşım, bir bellek içi veritabanıdır .

Yaygın olarak kullanılan başka bir yaklaşım. Sunucu ile DBMS arasına, tüm verilerini yalnızca bellekte depolayan başka bir veritabanı yerleştirilir. Aynı zamanda In-Memory-DB olarak da adlandırılır. Aynı veritabanına erişen birçok farklı sunucunuz varsa, In-Memory-DB'yi kullanarak önbelleği belirli bir sunucunun türüne göre düzenleyebilirsiniz.

Örnek:

Yaklaşım 4 - veritabanı kümesi . Birkaç salt okunur taban.

Başka bir çözüm, bir küme kullanmaktır: aynı türden birkaç DBMS, aynı verileri içerir. Aynı zamanda tüm veritabanlarından veri okuyabilir ve yalnızca birine yazabilirsiniz. Daha sonra veritabanlarının geri kalanıyla senkronize edilir.

Bu çok iyi bir çözüm çünkü yapılandırması kolay ve pratikte çalışıyor. Genellikle, veritabanına verileri değiştirmek için yapılan bir istek için, ona 10-100 veri okuma isteği gelir.

Hazırda bekletme modunda önbelleğe alma türleri

Hazırda Bekletme üç düzeyde önbelleğe almayı destekler:

  • Oturum düzeyinde önbelleğe alma (Oturum)
  • SessionFactory düzeyinde önbelleğe alma
  • İstekleri (ve sonuçlarını) önbelleğe alma

Bu sistemi şu şekilde temsil etmeye çalışabilirsiniz:

En basit önbelleğe alma türü ( birinci düzey önbellek olarak da adlandırılır ), Hazırda Bekletme oturumu düzeyinde uygulanır. Hazırda Bekletme, varsayılan olarak her zaman bu önbelleği kullanır ve devre dışı bırakılamaz .

Hemen aşağıdaki örneği ele alalım:

Employee director1 = session.get(Employee.class, 4);
Employee director2 = session.get(Employee.class, 4);

assertTrue(director1 == director2);

Burada veritabanına iki sorgu yapılacak gibi görünebilir, ancak bu öyle değil. Veritabanına yapılan ilk istekten sonra, Çalışan nesnesi önbelleğe alınır. Aynı oturumda nesneyi tekrar sorgularsanız, Hibernate aynı Java nesnesini döndürür.

Aynı nesne, nesne referanslarının bile aynı olacağı anlamına gelir. Gerçekten aynı nesne.

save() , update() , saveOrUpdate() , load() , get() , list() , iterate() ve scroll() yöntemleri her zaman birinci düzey önbelleği kullanır. Aslında eklenecek başka bir şey yok.

İkinci düzey önbelleğe alma

Birinci seviye önbellek oturum nesnesine bağlıysa, ikinci seviye önbellek de oturum nesnesine bağlıdır.Oturum Fabrikası. Bu, bu önbellekteki nesnelerin görünürlüğünün birinci seviye önbellekten çok daha geniş olduğu anlamına gelir.

Örnek:

Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();

Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();

assertTrue(director1 != director2);
assertTrue(director1.equals(director2));

Bu örnekte, veritabanına iki sorgu yapılacaktır. Hazırda Bekletme aynı nesneleri döndürür, ancak aynı nesne olmaz - farklı referansları olacaktır.

İkinci düzey önbelleğe alma varsayılan olarak devre dışıdır . Bu nedenle, veritabanına bir yerine iki sorgumuz var.

Etkinleştirmek için hibernate.cfg.xml dosyasına aşağıdaki satırları yazmanız gerekir:

<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>

İkinci düzey önbelleğe almayı etkinleştirdikten sonra, Hazırda Bekletme davranışı biraz değişecektir:

Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();

Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();

assertTrue(director1 == director2);

Ancak tüm bu manipülasyonlardan sonra ikinci düzey önbellek etkinleştirilecek ve yukarıdaki örnekte veritabanına yalnızca bir sorgu yürütülecektir.