Ohjelmointi

Kehitä yleinen välimuistipalvelu suorituskyvyn parantamiseksi

Oletetaan, että työtoveri pyytää sinulta luetteloa kaikista maailman maista. Koska et ole maantieteen asiantuntija, surffaat YK: n verkkosivustolle, lataat luettelon ja tulostat sen hänelle. Hän haluaa kuitenkin tutkia vain luetteloa; hän ei todellakaan ota sitä mukanaan. Koska viimeinen tarvitsemasi asia on toinen paperi työpöydällesi, syötät luettelon silppuriin.

Päivää myöhemmin toinen työtoveri pyytää samaa: luettelo kaikista maailman maista. Kiroat itseäsi siitä, että et pidä luetteloa, surffaat jälleen YK: n verkkosivustolle. Tällä vierailulla verkkosivustolla huomaat, että YK päivittää maaluettelon puolen vuoden välein. Lataat ja tulostat työtoverisi luettelon. Hän katsoo sitä, kiittää sinua ja jättää jälleen luettelon kanssasi. Tällä kertaa arkistoit luettelon viestillä liitteenä olevaan Post-it-muistiinpanoon, joka muistuttaa sinua hävittämisestä kuuden kuukauden kuluttua.

Tosiaan, seuraavien viikkojen aikana työtoverisi jatkavat luettelon pyytämistä uudelleen. Onnittelut itsestäsi asiakirjan jättämisestä, koska voit purkaa asiakirjan arkistokaapista nopeammin kuin voit purkaa sen verkkosivustolta. Arkistokaapisi konsepti tarttuu kiinni; pian kaikki alkavat laittaa esineitä kaappiin. Määritä kaapin käyttöä koskevat ohjeet, jotta kaappi ei kasvaisi epäjärjestyksessä. Virallisessa ominaisuudessasi arkistokaapin johtaja, käsket työtovereitasi sijoittamaan kaikkiin asiakirjoihin tarroja ja Post-it-muistiinpanoja, jotka tunnistavat asiakirjat ja heidän hävittämispäivänsä. Tunnisteet auttavat työtovereitasi löytämään etsimänsä asiakirjan, ja Post-it-muistiinpanot määrittävät, ovatko tiedot ajan tasalla.

Arkistokaappi kasvaa niin suosituksi, että siihen ei pian voida tehdä uusia asiakirjoja. Sinun on päätettävä, mitä heittää ulos ja mitä pitää. Vaikka heität kaikki vanhentuneet asiakirjat, kaappi on edelleen täynnä paperia. Kuinka päätät, mitkä vanhentumattomat asiakirjat hävitetään? Hävitätkö vanhimman asiakirjan? Voit hylätä vähiten käytetyt tai viimeksi käytetyt; molemmissa tapauksissa tarvitset lokin, joka on lueteltu, kun kutakin asiakirjaa käytettiin. Tai ehkä voit päättää, mitkä asiakirjat hävittää jonkin muun tekijän perusteella; päätös on puhtaasti henkilökohtainen.

Edellä mainitun todellisen analogian liittämiseksi tietokone maailmaan arkistokaappi toimii a kätkö: nopea muisti, joka tarvitsee ajoittain huoltoa. Välimuistissa olevat asiakirjat ovat välimuistissa olevat esineet, jotka kaikki ovat sinun asettamiesi standardien mukaisia, välimuistinhallinta. Välimuistin puhdistamisprosessia kutsutaan puhdistus. Koska välimuistissa olevat kohteet tyhjennetään tietyn ajan kuluttua, välimuistia kutsutaan a ajastettu välimuisti.

Tässä artikkelissa opit luomaan 100-prosenttisesti puhtaan Java-välimuistin, joka käyttää anonyymia taustalankaa vanhentuneiden kohteiden puhdistamiseen. Näet kuinka tällainen välimuisti suunnitellaan samalla kun ymmärrät eri malleihin liittyvät kompromissit.

Luo välimuisti

Tarpeeksi arkistokaappien analogiat: siirrymme verkkosivustoihin. Myös verkkosivustopalvelimien on käsiteltävä välimuistia. Palvelimet vastaanottavat toistuvasti tietopyyntöjä, jotka ovat identtisiä muiden pyyntöjen kanssa. Seuraavaa tehtävää varten sinun on rakennettava Internet-sovellus yhdelle maailman suurimmista yrityksistä. Neljän kuukauden kehityksen jälkeen, mukaan lukien monet unettomat yöt ja aivan liian monta Jolt colaa, sovellus menee kehitystestaukseen 1000 käyttäjän kanssa. 5000 käyttäjän sertifiointitesti ja sitä seuraava 20 000 käyttäjän tuotannon käyttöönotto seuraavat kehitystestausta. Kuitenkin, kun saat muistin ulkopuolella olevia virheitä, kun vain 200 käyttäjää testaa sovellusta, kehitystestaus pysähtyy.

Suorituskyvyn heikkenemisen lähteen havaitsemiseksi käytät profilointituotetta ja huomaat, että palvelin lataa useita kopioita tietokannasta ResultSets, joista kullakin on useita tuhansia tietueita. Tietueet muodostavat tuoteluettelon. Lisäksi tuoteluettelo on identtinen jokaiselle käyttäjälle. Luettelo ei ole riippuvainen käyttäjästä, kuten olisi voinut tapahtua, jos tuoteluettelo olisi tullut parametrisoidusta kyselystä. Päätät nopeasti, että yksi luettelon kopio voi palvella kaikkia samanaikaisia ​​käyttäjiä, joten välimuisti.

Kuitenkin herää joukko kysymyksiä, jotka sisältävät sellaisia ​​monimutkaisuuksia kuin:

  • Entä jos tuoteluettelo muuttuu? Kuinka välimuisti voi vanhentaa luettelot? Mistä tiedän, kuinka kauan tuoteluettelon tulisi olla välimuistissa ennen kuin se vanhenee?
  • Entä jos on olemassa kaksi erillistä tuoteluetteloa ja nämä kaksi luetteloa muuttuvat eri välein? Voinko kumota luettelot erikseen, vai onko niiden kaikkien oltava sama säilyvyysaika?
  • Entä jos välimuisti on tyhjä ja kaksi pyytäjää yrittää välimuistia täsmälleen samaan aikaan? Kun molemmat huomaavat, että se on tyhjä, luovatko he omat listansa ja yrittävät sitten laittaa kopionsa välimuistiin?
  • Entä jos tuotteet istuvat välimuistissa kuukausia ilman, että niitä käytetään? Eivätkö he syö muistia?

Näihin haasteisiin vastaamiseksi sinun on luotava ohjelmistojen välimuistipalvelu.

Arkistokaapin analogiassa ihmiset tarkistivat aina ensin kaapin, kun he etsivät asiakirjoja. Ohjelmiston on noudatettava samaa menettelyä: pyynnön on tarkistettava välimuistipalvelu ennen uuden luettelon lataamista tietokannasta. Ohjelmistokehittäjänä sinun vastuullasi on käyttää välimuistia ennen tietokantaan pääsyä. Jos tuoteluettelo on jo ladattu välimuistiin, käytät välimuistilistaa, jos se ei ole vanhentunut. Jos tuoteluetteloa ei ole välimuistissa, lataat sen tietokannasta ja välimuistiin heti.

merkintä: Ennen kuin jatkat välimuistipalvelun vaatimusten ja koodin noudattamista, kannattaa tarkistaa alla oleva sivupalkki "Välimuistin tallentaminen ja yhdistäminen". Se selittää yhdistäminen, siihen liittyvä käsite.

Vaatimukset

Hyvien suunnitteluperiaatteiden mukaisesti määritin välimuistipalvelun vaatimusten luettelon, jonka kehitämme tässä artikkelissa:

  1. Mikä tahansa Java-sovellus voi käyttää välimuistipalvelua.
  2. Objektit voidaan sijoittaa välimuistiin.
  3. Objektit voidaan purkaa välimuistista.
  4. Välimuistissa olevat kohteet voivat päättää itse, kun ne vanhenevat, mikä mahdollistaa maksimaalisen joustavuuden. Välimuistipalvelut, jotka vanhentavat kaikki objektit samaa vanhentumiskaavaa käyttäen, eivät tarjoa välimuistissa olevien kohteiden optimaalista käyttöä. Tämä lähestymistapa on riittämätön suurissa järjestelmissä, koska esimerkiksi tuoteluettelo voi muuttua päivittäin, kun taas luettelo myymälöistä saattaa muuttua vain kerran kuukaudessa.
  5. Matalan prioriteetin alla oleva taustalanka poistaa vanhentuneet välimuistissa olevat objektit.
  6. Välimuistipalvelua voidaan parantaa myöhemmin käyttämällä viimeksi käytettyä (LRU) tai vähiten käytettyä (LFU) puhdistusmekanismia.

Toteutus

Vaatimuksen 1 täyttämiseksi otamme käyttöön 100-prosenttisesti puhtaan Java-ympäristön. Tarjoamalla yleisölle saada ja aseta välimuistipalvelun menetelmiä, täytämme myös vaatimukset 2 ja 3.

Ennen kuin jatkan vaatimuksen 4 käsittelyä, mainitsen lyhyesti, että täytämme vaatimuksen 5 luomalla nimettömän ketjun välimuistinhallintaan; tämä säie alkaa staattisesta lohkosta. Täytämme myös vaatimuksen 6 tunnistamalla kohdat, joihin koodi lisätään myöhemmin LRU- ja LFU-algoritmien toteuttamiseksi. Kerron yksityiskohtaisemmin näistä vaatimuksista myöhemmin artikkelissa.

Palataan nyt vaatimukseen 4, jossa asioista tulee mielenkiintoisia. Jos jokaisen välimuistissa olevan objektin on itse määritettävä, onko se vanhentunut, sinulla on oltava tapa kysyä objektilta, onko se vanhentunut. Tämä tarkoittaa, että välimuistissa olevien kohteiden on kaikkien oltava tiettyjen sääntöjen mukaisia; saavutat sen Java-sovelluksessa toteuttamalla käyttöliittymän.

Aloitetaan säännöistä, jotka hallitsevat välimuistiin asetettuja objekteja.

  1. Kaikilla esineillä on oltava julkinen menetelmä nimeltä isExpired (), joka palauttaa Boolen arvon.
  2. Kaikilla esineillä on oltava julkinen menetelmä nimeltä getIdentifier (), joka palauttaa objektin, joka erottaa kohteen kaikista välimuistissa olevista.

merkintä: Ennen kuin siirryt suoraan koodiin, sinun on ymmärrettävä, että voit toteuttaa välimuistin monin tavoin. Olen löytänyt yli tusina erilaista toteutusta. Enhydra ja Caucho tarjoavat erinomaiset resurssit, jotka sisältävät useita välimuistitoteutuksia.

Tämän artikkelin välimuistipalvelun käyttöliittymäkoodi on luettelossa 1.

Listaus 1. Cacheable.java

/ ** * Otsikko: Välimuisti Kuvaus: Tämä käyttöliittymä määrittelee menetelmät, jotka kaikkien välimuistiin asetettavien objektien on toteutettava. * * Tekijänoikeus: Tekijänoikeus (c) 2001 * Yritys: JavaWorld * Tiedostonimi: Cacheable.java @author Jonathan Lurie @version 1.0 * / julkinen käyttöliittymä välimuistissa {/ * Vaadimalla kaikkia objekteja määrittämään omat vanhentumisajat, algoritmi erotetaan välimuistipalvelu, mikä tarjoaa maksimaalisen joustavuuden, koska jokainen objekti voi omaksua erilaisen vanhentumisstrategian. * / julkinen totuusarvo on vanhentunut (); / * Tämä menetelmä varmistaa, että välimuistipalvelu ei ole vastuussa välimuistiin sijoitettujen objektien yksilöllisestä tunnistamisesta. * / public Object getIdentifier (); } 

Mikä tahansa välimuistiin asetettu esine - a MerkkijonoEsimerkiksi - on käärittävä objektin sisälle, joka toteuttaa Välimuistissa käyttöliittymä. Listaus 2 on esimerkki yleisestä kääre-luokasta Välimuistissa oleva objekti; se voi sisältää minkä tahansa välimuistipalveluun tarvittavan objektin. Huomaa, että tämä kääreluokka toteuttaa Välimuistissa käyttöliittymä määritelty luettelossa 1.

Listaus 2. CachedManagerTestProgram.java

/ ** * Otsikko: Välimuisti * Kuvaus: Yleinen välimuistiobjektipaketti. Toteuttaa välimuistikäyttöliittymän * käyttää TimeToLive-stategiaa CacheObject-vanhenemiseen. * Tekijänoikeus: Tekijänoikeus (c) 2001 * Yritys: JavaWorld * Tiedostonimi: CacheManagerTestProgram.java * @author Jonathan Lurie * @version 1.0 * / public class CachedObject implementates Cacheable {// +++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++ / * Tätä muuttujaa käytetään määrittämään, onko objekti vanhentunut. * / private java.util.Date dateofExpiration = null; yksityisen kohteen tunniste = null; / * Tämä sisältää todellisen "arvon". Tämä on kohde, joka on jaettava. * / public Object object = tyhjä; // +++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++ public CachedObject (Object obj, Object id, int minutesToLive) {this.object = obj; this.identifier = id; // minutesToLive 0 tarkoittaa, että se elää toistaiseksi. if (minutesToLive! = 0) {dateofExpiration = uusi java.util.Date (); java.util.Calendar cal = java.util.Calendar.getInstance (); cal.setTime (dateofExpiration); cal.add (cal.MINUTE, minutesToLive); dateofExpiration = cal.getTime (); }} // +++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++ Julkinen Boolean isExpired () {// Muista, että elämä minuutti on nolla, niin se elää ikuisesti! jos (dateofExpiration! = null) {// vanhentumispäivää verrataan. if (dateofExpiration.before (uusi java.util.Date ())) {System.out.println ("CachedResultSet.isExpired: vanhentunut välimuistista! EXPIRE TIME:" + dateofExpiration.toString () + "CURRENT TIME:" + ( uusi java.util.Date ()). toString ()); palaa tosi; } else {System.out.println ("CachedResultSet.isExpired: Ei vanhentunut välimuistista!"); return false; }} else // Tämä tarkoittaa, että se elää ikuisesti! return false; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++ public Object getIdentifier () {return identifier; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++} 

Välimuistissa oleva objekti luokka paljastaa konstruktorimenetelmän, joka ottaa kolme parametria:

public CachedObject (Object obj, Object id, int minutesToLive) 

Alla olevassa taulukossa kuvataan nämä parametrit.

CachedObject-konstruktorin parametrien kuvaukset
NimiTyyppiKuvaus
ObjEsineJaettu objekti. Se on määritelty objektiksi, joka mahdollistaa maksimaalisen joustavuuden.
IdEsineId sisältää yksilöllisen tunnisteen, joka erottaa obj parametri kaikista muista välimuistissa olevista objekteista. Välimuistipalvelu ei ole vastuussa välimuistissa olevien esineiden ainutlaatuisuuden varmistamisesta.
minuuttiaToLiveIntMinuuttimäärä, jonka obj -parametri on kelvollinen välimuistissa. Tässä toteutuksessa välimuistipalvelu tulkitsee arvon nolla tarkoittaa, että objekti ei koskaan vanhene. Haluat ehkä muuttaa tätä parametria, jos sinun on vanhennettava objekteja alle minuutissa.

Konstruktorimenetelmä määrittää välimuistissa olevan objektin viimeisen käyttöpäivämäärän käyttämällä a aika elää strategia. Kuten nimestään käy ilmi, aika elää tarkoittaa, että tietyllä esineellä on kiinteä aika, jonka päättyessä sitä pidetään kuolleena. Lisäämällä minuuttiaToLive, rakentaja int Parametri, nykyiseen aikaan lasketaan viimeinen voimassaolopäivä. Tämä vanhentuminen on osoitettu luokan muuttujalle parasta ennen.

Nyt isExpired () Menetelmän on yksinkertaisesti määritettävä, onko parasta ennen on ennen nykyistä päivämäärää ja kellonaikaa tai sen jälkeen. Jos päivämäärä on ennen nykyistä aikaa ja välimuistissa olevan objektin katsotaan vanhentuneen, isExpired () method palauttaa true; jos päivämäärä on nykyisen ajan jälkeen, välimuistissa oleva objekti ei ole vanhentunut ja isExpired () palauttaa arvon false. Tottakai jos parasta ennen on nolla, mikä olisi tapaus, jos minuuttiaToLive oli nolla, sitten isExpired () method palauttaa aina väärän, mikä osoittaa, että välimuistissa oleva objekti elää ikuisesti.