Никога не пишете своето решение за кеширане
Друг начин за ускоряване на работата с базата данни е кеширането на обекти, които вече сме поискали по-рано.
важно! Никога не пишете свое собствено решение за кеширане. Тази задача има толкова много клопки, за които не сте и мечтали.
Проблем 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);
Само след всички тези манипулации ще бъде активиран кешът от второ ниво и в горния пример ще бъде изпълнена само една заявка към базата данни.
GO TO FULL VERSION