Skriv aldri caching-løsningen din

En annen måte å fremskynde arbeidet med databasen er å cache objekter som vi allerede har bedt om tidligere.

Viktig! Skriv aldri din egen hurtigbufferløsning. Denne oppgaven har så mange fallgruver du aldri har drømt om.

Utgave 1 - cache flush . Noen ganger oppstår hendelser når et objekt må fjernes fra hurtigbufferen eller oppdateres i hurtigbufferen. Den eneste måten å gjøre dette på er å sende alle forespørsler til databasen gjennom hurtigbuffermotoren. Ellers må du hver gang eksplisitt fortelle cachen hvilke objekter i den som skal slettes eller oppdateres.

Problem 2 - mangel på hukommelse . Bufring virker som en god idé helt til du finner ut at objekter i minnet tar opp mye plass. Du trenger flere titalls gigabyte med minne for at serverapplikasjonsbufferen skal fungere effektivt.

Og siden det alltid er mangel på minne, er det nødvendig med en effektiv strategi for å slette objekter fra cachen. Dette ligner litt på søppelsamleren i Java. Og som du husker, i flere tiår har de beste hodene funnet opp forskjellige måter å merke gjenstander etter generasjoner, osv.

Oppgave 3 - forskjellige strategier . Som praksis viser, er ulike strategier for lagring og oppdatering i cachen effektive for ulike objekter. Et effektivt hurtigbufringssystem kan ikke gjøre bare én strategi for alle objekter.

Oppgave 4 - Effektiv lagring av . Du kan ikke bare lagre objekter i hurtigbufferen. Objekter inneholder for ofte referanser til andre objekter osv. Med denne hastigheten trenger du ikke en søppeloppsamler: den har bare ikke noe å fjerne.

Derfor, i stedet for å lagre selve objektene, er det noen ganger mye mer effektivt å lagre verdiene til deres primitive felt. Og systemer for raskt å konstruere objekter basert på dem.

Som et resultat vil du få en hel virtuell DBMS i minnet, som skal fungere raskt og forbruke lite minne.

Databasebufring

I tillegg til caching direkte i et Java-program, er caching ofte organisert direkte i databasen.

Det er fire store tilnærminger:

Den første tilnærmingen er å denormalisere databasen . SQL-serveren lagrer data i minnet annerledes enn hvordan de er lagret i tabeller.

Når data er lagret på disk i tabeller, prøver utviklere veldig ofte å unngå dataduplisering så mye som mulig - denne prosessen kalles databasenormalisering. Så for å fremskynde arbeidet med data i minnet, utføres den omvendte prosessen - databasedenormalisering. En haug med relaterte tabeller kan allerede lagres i en kombinert form - i form av enorme tabeller, etc.

Den andre tilnærmingen er query caching . Og spørreresultater.

DBMS ser at det svært ofte kommer de samme eller lignende forespørsler til den. Så begynner den ganske enkelt å bufre disse forespørslene og svarene deres. Men samtidig må du sørge for at rader som har endret seg i databasen blir fjernet fra hurtigbufferen i tide.

Denne tilnærmingen kan være svært effektiv med et menneske som kan analysere spørringer og hjelpe DBMS med å finne ut hvordan de best kan bufres.

Den tredje tilnærmingen er en in-memory database .

En annen vanlig tilnærming. En annen database er plassert mellom serveren og DBMS, som bare lagrer alle dataene i minnet. Det kalles også In-Memory-DB. Hvis du har mange forskjellige servere som har tilgang til samme database, kan du ved å bruke In-Memory-DB organisere hurtigbufring basert på typen til en bestemt server.

Eksempel:

Tilnærming 4- databaseklynge . Flere skrivebeskyttede baser.

En annen løsning er å bruke en klynge: flere DBMS-er av samme type inneholder identiske data. Samtidig kan du lese data fra alle databaser, og skrive til kun én. Som så synkroniseres med resten av databasene.

Dette er en veldig god løsning fordi den er enkel å konfigurere og fungerer i praksis. Vanligvis, for én forespørsel til databasen om å endre data, kommer 10-100 forespørsler om å lese data til den.

Typer caching i dvalemodus

Hibernate støtter tre nivåer av caching:

  • Buffer på øktnivå (økt)
  • Bufring på SessionFactory-nivå
  • Bufferforespørsler (og resultatene deres)

Du kan prøve å representere dette systemet i form av en slik figur:

Den enkleste typen bufring (også kalt cache på første nivå ) implementeres på dvalemodus-øktnivå. Hibernate bruker alltid denne hurtigbufferen som standard og kan ikke deaktiveres .

La oss umiddelbart vurdere følgende eksempel:

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

assertTrue(director1 == director2);

Det kan se ut til at to spørringer til databasen vil bli utført her, men dette er ikke tilfelle. Etter den første forespørselen til databasen, vil Employee-objektet bli bufret. Og hvis du spør objektet på nytt i samme økt, vil Hibernate returnere det samme Java-objektet.

Det samme objektet betyr at selv objektreferanser vil være identiske. Det er egentlig det samme objektet.

Metodene save() , update() , saveOrUpdate() , load() , get() , list() , iterate() og scroll() vil alltid bruke cachen på første nivå. Egentlig er det ikke noe mer å legge til.

Andre nivå caching

Hvis cachen på første nivå er bundet til sesjonsobjektet, er cachen på andre nivå bundet til sesjonsobjektet.SessionFactory. Noe som betyr at synligheten til objekter i denne cachen er mye bredere enn i cachen på første nivå.

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 eksemplet vil to spørringer bli gjort til databasen. Hibernate vil returnere identiske objekter, men det vil ikke være det samme objektet - de vil ha forskjellige referanser.

Bufring på andre nivå er deaktivert som standard . Derfor har vi to spørringer til databasen i stedet for én.

For å aktivere det, må 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"/>

Etter å ha aktivert caching på andre nivå, vil dvalemodus endre seg litt:

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 etter alle disse manipulasjonene vil cachen på andre nivå bli aktivert, og i eksemplet ovenfor vil bare én spørring til databasen bli utført.