Skriv aldrig din cacheløsning

En anden måde at fremskynde arbejdet med databasen er at cache objekter, som vi allerede har anmodet om tidligere.

Vigtig! Skriv aldrig din egen caching-løsning. Denne opgave har så mange faldgruber, som du aldrig havde drømt om.

Udgave 1 - cache flush . Nogle gange opstår hændelser, når et objekt skal fjernes fra cachen eller opdateres i cachen. Den eneste måde at gøre dette kompetent på er at sende alle anmodninger til databasen gennem cache-motoren. Ellers skal du hver gang eksplicit fortælle cachen, hvilke objekter i den der skal slettes eller opdateres.

Problem 2 - mangel på hukommelse . Caching virker som en god idé, indtil du opdager, at objekter i hukommelsen fylder meget. Du skal bruge flere titusvis af gigabyte hukommelse for at serverapplikationens cache fungerer effektivt.

Og da der altid er mangel på hukommelse, er det nødvendigt med en effektiv strategi til sletning af objekter fra cachen. Dette minder lidt om skraldesamleren i Java. Og som du husker, har de bedste hjerner i årtier opfundet forskellige måder at markere objekter efter generationer osv.

Opgave 3 - forskellige strategier . Som praksis viser, er forskellige strategier til lagring og opdatering i cachen effektive for forskellige objekter. Et effektivt cachesystem kan ikke kun lave én strategi for alle objekter.

Problem 4 - Effektiv opbevaring af . Du kan ikke bare gemme objekter i cachen. Objekter indeholder for ofte referencer til andre objekter osv. Med denne hastighed behøver du ikke en skraldeopsamler: den har bare ikke noget at fjerne.

Derfor, i stedet for at gemme selve objekterne, er det nogle gange meget mere effektivt at gemme værdierne af deres primitive felter. Og systemer til hurtigt at konstruere objekter baseret på dem.

Som et resultat vil du få en hel virtuel DBMS i hukommelsen, som burde fungere hurtigt og forbruge lidt hukommelse.

Database caching

Udover at cache direkte i et Java-program, er caching ofte organiseret direkte i databasen.

Der er fire store tilgange:

Den første tilgang er at denormalisere databasen . SQL-serveren gemmer data i hukommelsen på en anden måde, end den er gemt i tabeller.

Når data gemmes på disk i tabeller, forsøger udviklere meget ofte at undgå dataduplikering så meget som muligt - denne proces kaldes databasenormalisering. Så for at fremskynde arbejdet med data i hukommelsen udføres den omvendte proces - databasedenormalisering. En masse relaterede tabeller kan allerede gemmes i en kombineret form - i form af enorme borde mv.

Den anden tilgang er query caching . Og forespørgselsresultater.

DBMS ser, at der meget ofte kommer de samme eller lignende anmodninger til den. Så begynder den simpelthen at cache disse anmodninger og deres svar. Men samtidig skal du sørge for, at rækker, der er ændret i databasen, fjernes fra cachen rettidigt.

Denne tilgang kan være meget effektiv med et menneske, der kan analysere forespørgsler og hjælpe DBMS med at finde ud af, hvordan de bedst cachelagres.

Den tredje tilgang er en in-memory-database .

En anden almindeligt anvendt tilgang. En anden database placeres mellem serveren og DBMS, som kun gemmer alle sine data i hukommelsen. Det kaldes også In-Memory-DB. Hvis du har mange forskellige servere, der tilgår den samme database, kan du ved hjælp af In-Memory-DB organisere caching baseret på typen af ​​en bestemt server.

Eksempel:

Approach 4- databaseklynge . Flere skrivebeskyttede baser.

En anden løsning er at bruge en klynge: flere DBMS'er af samme type indeholder identiske data. Samtidig kan du læse data fra alle databaser, og kun skrive til én. Som så synkroniseres med resten af ​​databaserne.

Dette er en meget god løsning, fordi den er nem at konfigurere og fungerer i praksis. Normalt, for en anmodning til databasen om at ændre data, kommer der 10-100 anmodninger om at læse data.

Typer af caching i Hibernate

Hibernate understøtter tre niveauer af caching:

  • Caching på sessionsniveau (session)
  • Caching på SessionFactory-niveau
  • Caching-anmodninger (og deres resultater)

Du kan prøve at repræsentere dette system i form af en sådan figur:

Den enkleste type cache (også kaldet cache på første niveau ) er implementeret på Hibernate-sessionsniveau. Hibernate bruger altid denne cache som standard og kan ikke deaktiveres .

Lad os straks overveje følgende eksempel:

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

assertTrue(director1 == director2);

Det kan se ud til, at to forespørgsler til databasen vil blive udført her, men det er ikke tilfældet. Efter den første anmodning til databasen, bliver Employee-objektet cachelagret. Og hvis du forespørger objektet igen i samme session, vil Hibernate returnere det samme Java-objekt.

Det samme objekt betyder, at selv objektreferencer vil være identiske. Det er virkelig det samme objekt.

Metoderne save() , update() , saveOrUpdate() , load() , get() , list() , iterate() og scroll() vil altid bruge cachen på første niveau. Faktisk er der ikke mere at tilføje.

Caching på andet niveau

Hvis cachen på første niveau er bundet til sessionsobjektet, er cachen på andet niveau bundet til sessionsobjektet.SessionFactory. Hvilket betyder, at synligheden af ​​objekter i denne cache er meget bredere end i cachen på første niveau.

Eksempel:

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

I dette eksempel vil der blive lavet to forespørgsler til databasen. Hibernate vil returnere identiske objekter, men det vil ikke være det samme objekt - de vil have forskellige referencer.

Caching på andet niveau er som standard deaktiveret . Derfor har vi to forespørgsler til databasen i stedet for én.

For at aktivere det, skal du skrive følgende linjer i hibernate.cfg.xml-filen:

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

Efter aktivering af caching på andet niveau, vil dvaletilstand ændre sig en smule:

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

Først efter alle disse manipulationer vil cachen på andet niveau blive aktiveret, og i eksemplet ovenfor vil kun én forespørgsel til databasen blive udført.