Programiranje

Razvijte splošno storitev predpomnjenja za izboljšanje učinkovitosti

Recimo, da vas sodelavec prosi za seznam vseh držav na svetu. Ker niste strokovnjak za geografijo, pobrskate do spletnega mesta Združenih narodov, prenesete seznam in mu ga natisnete. Želi pa si le ogledati seznam; pravzaprav je ne vzame s seboj. Ker je zadnja stvar, ki jo potrebujete, še en kos papirja na mizi, seznam pošljete v drobilnik.

Dan kasneje še ena sodelavka zahteva isto: seznam vseh držav na svetu. Preklinjajoč se, ker niste vodili seznama, spet brskate po spletnem mestu Združenih narodov. Ob tem obisku spletnega mesta opažate, da ZN vsakih šest mesecev posodabljajo seznam držav. Prenesete in natisnete seznam za svojega sodelavca. Poglej, se zahvali in spet seznam pusti pri vas. Tokrat seznam oddate s sporočilom na priloženi opombi Post-it, ki vas opomni, da ga po šestih mesecih zavržete.

Seveda v naslednjih nekaj tednih sodelavci še naprej zahtevajo seznam znova in znova. Čestitate si, da ste vložili dokument, saj lahko dokument hitreje izvlečete iz kartoteke kot s spletnega mesta. Koncept vaše kartoteke se ujame; kmalu vsi začnejo dajati predmete v vašo omarico. Da preprečite neorganiziranost omare, določite smernice za njeno uporabo. V svoji uradni vlogi kot vodja kartoteke, svojim sodelavcem naročite, naj na vse dokumente namestijo nalepke in zapiske po objavi, ki identificirajo dokumente in datum njihovega zavržka / roka uporabnosti. Nalepke pomagajo sodelavcem poiskati iskani dokument, zapiski Post-it pa ugotavljajo, ali so podatki posodobljeni.

Kartoteka je tako priljubljena, da kmalu vanjo ne morete vložiti novih dokumentov. Odločiti se morate, kaj izvreči in kaj obdržati. Čeprav zavržete vse potekle dokumente, je v omari še vedno polno papirja. Kako se odločite, katere dokumente brez roka uporabnosti boste zavrgli? Ali zavržete najstarejši dokument? Lahko zavržete najmanj pogosto uporabljene ali najmanj nedavno uporabljene; v obeh primerih bi potrebovali dnevnik, ki bi bil naveden ob dostopu do vsakega dokumenta. Ali pa se lahko na podlagi neke druge določitve odločite, katere dokumente boste zavrgli; odločitev je povsem osebna.

Za povezavo zgornje analogije iz resničnega sveta z računalniškim svetom arhiv deluje kot predpomnilnik: hitri pomnilnik, ki občasno potrebuje vzdrževanje. Dokumenti v predpomnilniku so predpomnjeni predmeti, ki ustrezajo standardom, ki ste jih postavili vi, predpomnilnik. Postopek čiščenja predpomnilnika se imenuje čiščenje. Ker se predpomnjeni predmeti po določenem času očistijo, se predpomnilnik imenuje a časovni predpomnilnik.

V tem članku boste izvedeli, kako ustvariti 100-odstotno čisti predpomnilnik Java, ki uporablja anonimno nit v ozadju za čiščenje poteklih elementov. Videli boste, kako oblikovati tak predpomnilnik, hkrati pa razumeti kompromise, povezane z različnimi modeli.

Zgradite predpomnilnik

Dovolj analogij v omari: pojdimo na spletna mesta. Spletni strežniki se morajo ukvarjati tudi s predpomnjenjem. Strežniki večkrat prejmejo zahteve za informacije, ki so enake drugim zahtevam. Za naslednjo nalogo morate zgraditi internetno aplikacijo za eno največjih svetovnih podjetij. Po štirih mesecih razvoja, vključno s številnimi neprespanimi nočmi in preveč Jolt colami, aplikacija začne s 1.000 uporabniki razvojnega testiranja. Po razvojnem preizkusu sledi preizkus certificiranja 5000 uporabnikov in nadaljnje uvajanje proizvodnje 20.000 uporabnikov. Ko pa prejmete napake brez pomnilnika, medtem ko aplikacijo preizkusi le 200 uporabnikov, se razvojno testiranje ustavi.

Če želite razbrati vir poslabšanja zmogljivosti, uporabite izdelek za profiliranje in odkrijte, da strežnik naloži več kopij baze podatkov ResultSets, od katerih ima vsak po več tisoč zapisov. Zapisi sestavljajo seznam izdelkov. Poleg tega je seznam izdelkov enak za vsakega uporabnika. Seznam ni odvisen od uporabnika, kot bi se morda zgodilo, če bi bil seznam izdelkov rezultat parametrizirane poizvedbe. Hitro se odločite, da bi en izvod seznama lahko služil vsem sočasnim uporabnikom, zato ga predpomnite.

Vendar se pojavljajo številna vprašanja, ki vključujejo takšno zapletenost, kot so:

  • Kaj, če se seznam izdelkov spremeni? Kako lahko predpomnilnik preneha veljati za sezname? Kako bom vedel, kako dolgo mora seznam izdelkov ostati v predpomnilniku, preden poteče?
  • Kaj pa, če obstajata dva različna seznama izdelkov in se seznama spreminjata v različnih intervalih? Ali lahko potečem veljavnost vsakega seznama posebej, ali morajo imeti vsi enak rok uporabnosti?
  • Kaj pa, če je predpomnilnik prazen in dva vlagatelja poskusita predpomnilnika natančno istočasno? Ko bosta oba ugotovila, da je prazen, bosta ustvarila lastne sezname, nato pa bosta oba poskušala shraniti svoje kopije v predpomnilnik?
  • Kaj pa, če predmeti mesece sedijo v predpomnilniku, ne da bi bili do njih dostopni? Ne bodo pojedli spomina?

Za reševanje teh izzivov morate zgraditi storitev predpomnjenja programske opreme.

Po analogiji omare so ljudje pri iskanju dokumentov vedno najprej pregledali omaro. Vaša programska oprema mora izvajati enak postopek: zahteva mora preveriti storitev predpomnjenja, preden naloži nov seznam iz baze podatkov. Kot razvijalec programske opreme je vaša odgovornost dostop do predpomnilnika pred dostopom do baze podatkov. Če je seznam izdelkov že naložen v predpomnilnik, uporabite predpomnjeni seznam, pod pogojem, da ni potekel. Če seznama izdelkov ni v predpomnilniku, ga naložite iz baze podatkov in takoj predpomnite.

Opomba: Preden nadaljujete z zahtevami in kodo storitve predpomnjenja, si oglejte spodnjo stransko vrstico »Caching Versus Pooling«. Pojasnjuje združevanje, povezan koncept.

Zahteve

V skladu z dobrimi načeli oblikovanja sem določil seznam zahtev za storitev predpomnjenja, ki ga bomo razvili v tem članku:

  1. Vsaka aplikacija Java lahko dostopa do storitve predpomnjenja.
  2. Predmeti se lahko shranijo v predpomnilnik.
  3. Predmete lahko izvlečete iz predpomnilnika.
  4. Predpomnjeni predmeti lahko sami določijo, kdaj potečejo, s čimer omogočajo največjo prilagodljivost. Storitve predpomnjenja, ki potečejo vsem objektom z isto formulo poteka, ne zagotavljajo optimalne uporabe predpomnjenih predmetov. Ta pristop je v obsežnih sistemih neustrezen, saj se na primer seznam izdelkov lahko spreminja vsak dan, medtem ko se seznam lokacij trgovin spreminja le enkrat na mesec.
  5. Nit v ozadju, ki se izvaja pod nizko prioriteto, odstrani predpomnjene predmete, ki jim je potekel.
  6. Storitev predpomnjenja je mogoče kasneje izboljšati z uporabo mehanizma za čiščenje, ki se uporablja nedavno (LRU) ali najmanj pogosto uporablja (LFU).

Izvajanje

Da bi izpolnili zahtevo 1, smo sprejeli 100-odstotno čisto Java okolje. Z zagotavljanjem javnega dobili in nastavite metode v storitvi predpomnjenja, izpolnjujemo tudi zahteve 2 in 3.

Preden nadaljujem z razpravo o zahtevi 4, bom na kratko omenil, da bomo zahtevo 5 izpolnili z ustvarjanjem anonimne niti v upravitelju predpomnilnika; ta nit se začne v statičnem bloku. Prav tako izpolnjujemo zahtevo 6 z določitvijo točk, kamor bi pozneje dodali kodo za izvajanje algoritmov LRU in LFU. Podrobneje o teh zahtevah bom nadaljeval v članku.

Zdaj pa nazaj k Zahtevi 4, kjer stvari postanejo zanimive. Če mora vsak predpomnjeni objekt sam določiti, ali je potekel, potem morate imeti možnost, da predmet vprašate, ali je potekel. To pomeni, da morajo vsi predmeti v predpomnilniku ustrezati določenim pravilom; to dosežete v Javi z uporabo vmesnika.

Začnimo s pravili, ki urejajo predmete, shranjene v predpomnilniku.

  1. Vsi predmeti morajo imeti poklicano javno metodo isExpired (), ki vrne logično vrednost.
  2. Vsi predmeti morajo imeti poklicano javno metodo getIdentifier (), ki vrne objekt, ki razlikuje objekt od vseh drugih v predpomnilniku.

Opomba: Preden skočite naravnost v kodo, morate razumeti, da lahko predpomnilnik uveljavite na več načinov. Našel sem več kot ducat različnih izvedb. Enhydra in Caucho zagotavljata odlične vire, ki vsebujejo več izvedb predpomnilnika.

Kodo vmesnika za storitev predpomnjenja tega članka najdete v seznamu 1.

Seznam 1. Cacheable.java

/ ** * Naslov: Opis predpomnjenja: Ta vmesnik določa metode, ki jih morajo izvajati vsi predmeti, ki želijo biti postavljeni v predpomnilnik. * * Avtorske pravice: Avtorske pravice (c) 2001 * Podjetje: JavaWorld * Ime datoteke: Cacheable.java @author Jonathan Lurie @version 1.0 * / javni vmesnik Cacheable {/ * Ker vsi predmeti določajo svoje poteke, je algoritem izvlečen iz storitev predpomnjenja in s tem zagotavlja največjo prilagodljivost, saj lahko vsak predmet sprejme drugačno strategijo poteka. * / javni logični isExpired (); / * Ta metoda bo zagotovila, da storitev predpomnjenja ni odgovorna za enolično prepoznavanje predmetov, shranjenih v predpomnilniku. * / javni Object getIdentifier (); } 

Vsak predmet, shranjen v predpomnilniku - a Vrvicana primer - mora biti zavit znotraj predmeta, ki izvaja Predpomnilnik vmesnik. Seznam 2 je primer imenovanega generičnega razreda ovojnice CachedObject; lahko vsebuje kateri koli predmet, ki ga je treba namestiti v storitev predpomnjenja. Upoštevajte, da ta razred ovojnice izvaja Predpomnilnik vmesnik, opredeljen v seznamu 1.

Seznam 2. CachedManagerTestProgram.java

/ ** * Naslov: Predpomnjenje * Opis: Obloga splošnega predpomnilnika. Izvaja vmesnik Cacheable * uporablja stateTimeToLive za iztek CacheObject. * Avtorske pravice: Copyright (c) 2001 * Podjetje: JavaWorld * Ime datoteke: CacheManagerTestProgram.java * @author Jonathan Lurie * @version 1.0 * / javni razred CachedObject izvaja Cacheable {// ++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++ / * Ta spremenljivka bo uporabljena za ugotavljanje, ali je predmet potekel. * / private java.util.Date dateofExpiration = null; zasebni identifikator predmeta = null; / * Ta vsebuje dejansko "vrednost". To je predmet, ki ga je treba deliti. * / javni objekt objekt = null; // ++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++ javni CachedObject (Object obj, Object id, int minutesToLive) {this.object = obj; this.identifier = id; // minutesToLive of 0 pomeni, da živi neomejeno dolgo. if (minutesToLive! = 0) {dateofExpiration = nov java.util.Date (); java.util.Calendar cal = java.util.Calendar.getInstance (); cal.setTime (dateofExpiration); cal.add (cal.MINUTE, minutesToLive); dateofExpiration = cal.getTime (); }} // +++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++ public boolean isExpired () {// Ne pozabite, če je minut za življenje nič, potem živi večno! if (dateofExpiration! = null) {// primerjamo datum poteka. if (dateofExpiration.before (new java.util.Date ())) {System.out.println ("CachedResultSet.isExpired: Expired from Cache! EXPIRE TIME:" + dateofExpiration.toString () + "TEKOČI ČAS:" + ( nov java.util.Date ()). toString ()); vrni res; } else {System.out.println ("CachedResultSet.isExpired: Poteklo ni iz predpomnilnika!"); vrni false; }} else // To pomeni, da živi večno! vrni false; } // +++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++ javni objekt getIdentifier () {identifikator vrnitve; } // +++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++}} 

The CachedObject razred izpostavi konstruktorsko metodo, ki ima tri parametre:

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

Spodnja tabela opisuje te parametre.

Opisi parametrov konstruktorja CachedObject
ImeTipOpis
ObjPredmetPredmet, ki je v skupni rabi. Opredeljen je kot objekt, ki omogoča največjo prilagodljivost.
IdPredmetId vsebuje enoličen identifikator, ki razlikuje obj iz vseh drugih predmetov, ki se nahajajo v predpomnilniku. Služba za predpomnjenje ni odgovorna za zagotavljanje edinstvenosti predmetov v predpomnilniku.
minutesToLiveIntŠtevilo minut, ki jih obj parameter velja v predpomnilniku. Pri tej izvedbi storitev predpomnjenja interpretira vrednost nič, da pomeni, da objekt nikoli ne poteče. Ta parameter boste morda želeli spremeniti, če boste morali predmetom poteči v manj kot eni minuti.

Konstruktorska metoda določi datum poteka predmeta v predpomnilniku z uporabo čas za življenje strategijo. Kot že ime pove, čas do življenja pomeni, da ima določen predmet določen čas, po zaključku katerega se šteje za mrtvega. Z dodajanjem minutesToLive, konstruktorjev int za trenutni čas se izračuna datum poteka. Ta potek je dodeljen spremenljivki razreda datum izteka veljavnosti.

Zdaj pa isExpired () metoda mora preprosto ugotoviti, ali je datum izteka veljavnosti je pred ali po trenutnem datumu in uri. Če je datum pred trenutnim časom in se šteje, da je predpomnjeni predmet potekel, se isExpired () metoda vrne true; če je datum po trenutnem času, predpomnjeni objekt ni potekel in isExpired () vrne false. Seveda, če datum izteka veljavnosti je nič, kar bi bilo v primeru, če minutesToLive je bila nič, potem je isExpired () metoda vedno vrne false, kar pomeni, da predpomnjeni objekt živi večno.

$config[zx-auto] not found$config[zx-overlay] not found