Никога не пишете своето решение за кеширане

Друг начин за ускоряване на работата с базата данни е кеширането на обекти, които вече сме поискали по-рано.

важно! Никога не пишете свое собствено решение за кеширане. Тази задача има толкова много клопки, за които не сте и мечтали.

Проблем 1 - прочистване на кеша . Понякога възникват събития, когато даден обект трябва да бъде премахнат от кеша or актуализиран в кеша. Единственият начин да направите това компетентно е да прехвърлите всички заявки към базата данни през кеш машината. В противен случай всеки път ще трябва изрично да казвате на кеша кои обекти в него трябва да бъдат изтрити or актуализирани.

Проблем 2 - липса на памет . Кеширането изглежда като страхотна идея, докато не откриете, че обектите в паметта заемат много място. Имате нужда от допълнителни десетки гигаbyteа памет, за да работи ефективно кешът на сървърното приложение.

И тъй като винаги има недостиг на памет, е необходима ефективна стратегия за изтриване на обекти от кеша. Това е донякъде подобно на събирача на отпадъци в Java. И Howто си спомняте, от десетилетия най-добрите умове измислят различни начини за маркиране на обекти по поколения и т.н.

Задача 3 - различни стратегии . Както показва практиката, различни стратегии за съхранение и актуализиране в кеша са ефективни за различни обекти. Една ефективна система за кеширане не може да изпълнява само една стратегия за всички обекти.

Проблем 4 - Ефективно съхранение на . Не можете просто да съхранявате обекти в кеша. Обектите твърде често съдържат препратки към други обекти и т. н. При тази скорост няма да имате нужда от събирач на отпадъци: той просто няма да има Howво да премахва.

Следователно, instead of да съхранявате самите обекти, понякога е много по-ефективно да съхранявате стойностите на техните примитивни полета. И системи за бързо конструиране на обекти на тяхна основа.

В резултат на това ще получите цяла виртуална СУБД в паметта, която трябва да работи бързо и да консумира малко памет.

Кеширане на база данни

В допълнение към директното кеширане в Java програма, кеширането често се организира директно в базата данни.

Има четири големи подхода:

Първият подход е да се денормализира базата данни . SQL сървърът съхранява данни в паметта по различен начин от начина, по който се съхраняват в таблици.

Когато данните се съхраняват на диск в таблици, много често разработчиците се опитват да избегнат дублирането на данни, доколкото е възможно - този процес се нарича нормализиране на базата данни. Така че, за да се ускори работата с данни в паметта, се извършва обратният процес - денормализиране на базата данни. Куп свързани таблици вече могат да се съхраняват в комбинирана форма - под формата на огромни таблици и т.н.

Вторият подход е кеширане на заявки . И резултати от заявката.

СУБД вижда, че много често при нея идват същите or подобни заявки. След това просто започва да кешира тези заявки и техните отговори. Но в същото време трябва да се уверите, че редовете, които са променени в базата данни, се премахват от кеша своевременно.

Този подход може да бъде много ефективен с човешко същество, което може да анализира заявки и да помогне на СУБД да разбере How най-добре да ги кешира.

Третият подход е база данни в паметта .

Друг често използван подход. Друга база данни се поставя между сървъра и СУБД, която съхранява всичките си данни само в паметта. Нарича се още In-Memory-DB. Ако имате много различни сървъри, които имат достъп до една и съща база данни, тогава с помощта на In-Memory-DB можете да организирате кеширането въз основа на типа на конкретен сървър.

Пример:

Подход 4 - клъстер от база данни . Няколко бази само за четене.

Друго решение е използването на клъстер: няколко СУБД от един и същи тип съдържат идентични данни. В същото време можете да четете данни от всички бази данни и да пишете само в една. Което след това се синхронизира с останалите бази данни.

Това е много добро решение, защото е лесно за конфигуриране и работи на практика. Обикновено за една заявка към базата данни за промяна на данни идват 10-100 заявки за четене на данни.

Видове кеширане в Hibernate

Hibernate поддържа три нива на кеширане:

  • Кеширане на ниво сесия (сесия)
  • Кеширане на ниво SessionFactory
  • Кеширане на заявки (и техните резултати)

Можете да опитате да представите тази система под формата на такава фигура:

Най-простият тип кеширане (наричан още кеш от първо ниво ) се реализира на ниво сесия на Hibernate. Hibernate винаги използва този кеш по подразбиране и не може да бъде деактивиран .

Нека веднага разгледаме следния пример:

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

assertTrue(director1 == director2);

Може да изглежда, че тук ще бъдат изпълнени две заявки към базата данни, но това не е така. След първата заявка към базата данни обектът Employee ще бъде кеширан. И ако заявите обекта отново в същата сесия, Hibernate ще върне същия Java обект.

Същият обект означава, че дори препратките към обекти ще бъдат идентични. Това наистина е един и същ обект.

Методите save() , update() , saveOrUpdate() , load() , get() , list() , iterate() и scroll() винаги ще използват кеша от първо ниво. Всъщност няма Howво повече да се добави.

Кеширане от второ ниво

Ако кешът от първо ниво е обвързан с обекта на сесията, тогава кешът от второ ниво е обвързан с обекта на сесията.SessionFactory. Което означава, че видимостта на обектите в този кеш е много по-широка, отколкото в кеша от първо ниво.

Пример:

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));

В този пример ще бъдат напequalsи две заявки към базата данни. Hibernate ще върне идентични обекти, но това няма да е един и същ обект - те ще имат различни препратки.

Кеширането от второ ниво е деактивирано по подразбиране . Следователно имаме две заявки към базата данни instead of една.

За да го активирате, трябва да напишете следните редове във file hibernate.cfg.xml:

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

След като активирате кеширането от второ ниво, поведението на Hibernate ще се промени малко:

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);

Само след всички тези манипулации ще бъде активиран кешът от второ ниво и в горния пример ще бъде изпълнена само една заявка към базата данни.