Programavimas

Paskirstyti sandoriai pavasarį su XA ir be jos

Nors pavasarį paskirstytoms operacijoms paprastai naudojama „Java Transaction“ API ir XA protokolas, turite kitų galimybių. Optimalus diegimas priklauso nuo jūsų programos naudojamų išteklių tipų ir kompromisų, kuriuos norite atlikti tarp našumo, saugumo, patikimumo ir duomenų vientisumo. Šioje „JavaWorld“ funkcijoje „SpringSource“ Davidas Syeris nurodo septynis paskirstytų operacijų modelius „Spring“ programose, iš kurių trys yra su XA ir keturi be. Lygis: tarpinis

„Spring Framework“ palaikymas „Java Transaction API“ (JTA) leidžia programoms naudoti paskirstytas operacijas ir XA protokolą, nevykdant „Java EE“ konteinerio. Net ir turint šią paramą, XA yra brangus ir gali būti nepatikimas ar sudėtingas administruoti. Taigi gali būti netikėta staigmena, kad tam tikros klasės programos gali visiškai išvengti XA naudojimo.

Kad galėčiau lengviau suprasti įvairius požiūrius į paskirstytus sandorius, išanalizuosiu septynis operacijų apdorojimo modelius ir pateiksiu kodų pavyzdžius, kad jie būtų konkretūs. Pateiksiu modelius atvirkštine saugos ar patikimumo tvarka, pradedant nuo tų, kurioms užtikrinta aukščiausia duomenų vientisumo ir atomiškumo garantija esant bendroms aplinkybėms. Judant žemyn sąraše, bus taikoma daugiau įspėjimų ir apribojimų. Modeliai taip pat yra maždaug atvirkštine vykdymo laiko tvarka (pradedant brangiausiu). Modeliai yra architektūriniai arba techniniai, priešingai nei verslo modeliai, todėl nesusitelkiu į verslo naudojimo atvejį, tik į minimalų kodo kiekį, kad galėčiau pamatyti kiekvieną modelį.

Atminkite, kad tik pirmuose trijuose modeliuose naudojama XA, ir jie gali būti nepasiekiami arba nepriimtini dėl našumo priežasčių. Aš neaptariu XA modelių taip plačiai, kaip kiti, nes jie yra aprašyti kitur, nors pateikiu paprastą pirmojo pavyzdį. Perskaitę šį straipsnį sužinosite, ką galite ir ko negalite daryti su paskirstytosiomis operacijomis ir kaip ir kada vengti naudoti XA, o kada ne.

Paskirstyti sandoriai ir atomiškumas

A platinamas sandoris yra tas, kuris apima daugiau nei vieną sandorio šaltinį. Sandorio išteklių pavyzdžiai yra jungtys, skirtos bendrauti su reliacinėmis duomenų bazėmis ir pranešimų tarpine programine įranga. Dažnai tokiame šaltinyje yra API, kuri atrodo panašiai pradėti (), grįžti atgal (), įsipareigoti (). „Java“ pasaulyje sandorių šaltiniai paprastai rodomi kaip pagrindinės platformos teikiamos gamyklos produktas: duomenų bazei tai yra Ryšys (gaminamas Duomenų šaltinis) arba „Java Persistence API“ (JPA) „EntityManager“; „Java Message Service“ (JMS), tai yra Sesija.

Tipiškame pavyzdyje JMS pranešimas suaktyvina duomenų bazės atnaujinimą. Suskirstyta į laiko juostą, sėkminga sąveika vyksta maždaug taip:

  1. Pradėkite susirašinėjimo operaciją
  2. Gauti pranešimą
  3. Pradėti duomenų bazės operaciją
  4. Atnaujinti duomenų bazę
  5. Įvykdyti duomenų bazės operaciją
  6. Įvykdyti susirašinėjimo operaciją

Jei naujinant įvyko duomenų bazės klaida, pvz., Suvaržymo pažeidimas, pageidautina seka atrodys taip:

  1. Pradėkite susirašinėjimo operaciją
  2. Gauti pranešimą
  3. Pradėti duomenų bazės operaciją
  4. Atnaujinkite duomenų bazę, nepavyks!
  5. Atkurti duomenų bazės operaciją
  6. Atšaukti susirašinėjimo operaciją

Tokiu atveju pranešimas grįžta į tarpinę programinę įrangą po paskutinio atkūrimo ir tam tikru momentu grįžta, kad būtų gautas vykdant kitą operaciją. Paprastai tai yra geras dalykas, nes priešingu atveju jūs negalite įrašyti, kad įvyko gedimas. (Automatinio pakartotinio bandymo ir išimčių tvarkymo mechanizmai nepatenka į šio straipsnio taikymo sritį.)

Svarbus abiejų laiko juostų bruožas yra tas, kad jos yra atominis, suformuojantis vieną logišką operaciją, kuri arba visiškai pavyksta, arba visiškai nepavyksta.

Bet kas garantuoja, kad laiko juosta atrodo kaip kuri nors iš šių sekų? Turi įvykti tam tikras sandorių išteklių sinchronizavimas, kad, jei vienas įsipareigotų, jie abu padarytų ir atvirkščiai. Priešingu atveju visas sandoris nėra atominis. Operacija yra paskirstoma, nes yra susiję keli ištekliai, be sinchronizavimo ji nebus atominė. Techniniai ir konceptualūs paskirstytų operacijų sunkumai yra susiję su išteklių sinchronizavimu (arba jo trūkumu).

Pirmieji trys toliau aptarti modeliai yra pagrįsti XA protokolu. Kadangi šie modeliai buvo plačiai aprėpti, aš čia jų plačiau nenagrinėsiu. Tie, kurie žino XA modelius, gali norėti pereiti prie „Shared Transaction Resource“ modelio.

Visas XA su 2PC

Jei jums reikia beveik neperšaunamų garantijų, kad jūsų programos operacijos bus atkurtos po pertraukos, įskaitant serverio gedimą, tada „Full XA“ yra jūsų vienintelis pasirinkimas. Šiuo atveju operacijai sinchronizuoti naudojamas bendras išteklius yra specialus operacijų tvarkytuvas, kuris koordinuoja informaciją apie procesą naudodamas XA protokolą. „Java“, kūrėjo požiūriu, protokolas yra veikiamas per JTA „UserTransaction“.

Būdama sistemos sąsaja, XA yra įgalinanti technologija, kurios dauguma kūrėjų niekada nemato. Jie turi žinoti, kad tai yra ten, ką tai įgalina, ką kainuoja ir kokią įtaką jie naudoja sandorių ištekliams. Išlaidos gaunamos iš dviejų fazių įsipareigojimų (2PC) protokolo, kurį operacijų valdytojas naudoja užtikrindamas, kad visi ištekliai susitartų dėl operacijos rezultatų dar nepasibaigus.

Jei programa įgalinta „Spring“, ji naudoja „Spring“ „JtaTransactionManager“ ir pavasario deklaratyvus operacijų valdymas, kad būtų paslėpta pagrindinio sinchronizavimo informacija. Kūrėjo skirtumas tarp XA ir XA nenaudojimo yra gamyklinių išteklių konfigūravimas: Duomenų šaltinis egzempliorių ir programos operacijų tvarkytuvę. Šiame straipsnyje pateikiama pavyzdinė programa ( atomikos-db projektas), kuris iliustruoja šią konfigūraciją. Duomenų šaltinis egzemplioriai ir operacijų tvarkytuvė yra vieninteliai XA arba JTA specifiniai programos elementai.

Norėdami pamatyti imties veikimą, atlikite vieneto bandymus com.springsource.open.db. Paprastas „MulipleDataSourceTests“ klasė tiesiog įterpia duomenis į du duomenų šaltinius ir tada naudoja „Spring“ integravimo palaikymo funkcijas operacijai atkurti, kaip parodyta 1 sąraše:

Sąrašas 1. Sandorių grąžinimas

@Transactional @Test public void testInsertIntoTwoDataSources () išmeta išimtį {int count = getJdbcTemplate (). Update ("INSERT into T_FOOS (id, name, foo_date) values ​​(?,?, Null)", 0, "foo"); assertEquals (1, skaičius); count = getOtherJdbcTemplate () .update ("INSERT into T_AUDITS (id, operation, name, audit_date) values ​​(?,?,?,?)", 0, "INSERT", "foo", new Date ()); assertEquals (1, skaičius); // Pakeitimai bus grąžinti išėjus iš šio metodo}

Tada „MulipleDataSourceTests“ patikrina, ar abi operacijos buvo grąžintos atgal, kaip parodyta 2 sąraše:

Sąrašas 2. Patvirtinimo grąžinimas

@AfterTransaction public void checkPostConditions () {int count = getJdbcTemplate (). QueryForInt ("pasirinkite skaičių (*) iš T_FOOS"); // Šį pakeitimą grąžino bandymo sistemos assertEquals (0, count); count = getOtherJdbcTemplate (). queryForInt ("pasirinkite skaičių (*) iš T_AUDITS"); // Tai taip pat grįžo dėl XA assertEquals (0, count); }

Norėdami geriau suprasti, kaip veikia pavasario operacijų valdymas ir kaip jį paprastai sukonfigūruoti, žr. „Spring Reference Guide“.

XA su 1PC optimizavimu

Šis modelis yra optimizavimas, kurį daugelis operacijų valdytojų naudoja, kad išvengtų 2PC pridėtinių išlaidų, jei operacija apima vieną šaltinį. Tikėtumėte, kad jūsų programų serveris sugebės tai išsiaiškinti.

„XA“ ir „Last Resource Gambit“

Kitas daugelio XA operacijų valdytojų bruožas yra tas, kad jie vis tiek gali pateikti tas pačias atkūrimo garantijas, kai visi šaltiniai, išskyrus vieną, gali naudoti XA, kaip jie gali, kai jie visi yra. Jie tai daro užsakydami išteklius ir naudodami ne XA išteklius kaip lemiamą balsą. Jei nepavyksta įsipareigoti, visus kitus išteklius galima sugrąžinti atgal. Tai beveik 100 proc. Neperšaunama, bet ne visai tai. Kai nepavyksta, jis sugenda nepalikdamas daug pėdsakų, nebent būtų imtasi papildomų veiksmų (kaip daroma kai kuriuose aukščiausio lygio diegimuose).

Bendro operacijos išteklių modelis

Puikus sudėtingumo mažinimo ir kai kurių sistemų pralaidumo didinimo būdas yra visiškai pašalinti XA poreikį užtikrinant, kad visi sistemos sandorių ištekliai būtų faktiškai paremti tuo pačiu ištekliu. Tai akivaizdžiai neįmanoma visais apdorojimo naudojimo atvejais, tačiau jis yra toks pat tvirtas kaip XA ir paprastai daug greičiau. Bendro operacijos išteklių modelis yra neperšaunamas, tačiau būdingas tam tikroms platformoms ir apdorojimo scenarijams.

Paprastas ir daugeliui pažįstamas šio modelio pavyzdys yra dalijimasis duomenų baze Ryšys tarp komponento, kuris naudoja objekto reliacinį atvaizdavimą (ORM), su komponentu, kuris naudoja JDBC. Taip atsitinka, kai naudojatės pavasario operacijų tvarkytuvėmis, palaikančiomis ORM įrankius, pvz., „Hibernate“, „EclipseLink“ ir „Java Persistence API“ (JPA). Tas pats sandoris gali būti saugiai naudojamas visuose ORM ir JDBC komponentuose, paprastai valdomuose iš viršaus atliekant paslaugos lygio metodo vykdymą, kai operacija yra kontroliuojama.

Kitas veiksmingas šio modelio panaudojimas yra pranešimų valdomas vienos duomenų bazės atnaujinimas (kaip paprastame pavyzdyje šio straipsnio įžangoje). Pranešimų ir tarpinės programos turi saugoti savo duomenis kažkur, dažnai reliacinėje duomenų bazėje. Norint įgyvendinti šį modelį, tereikia nukreipti pranešimų sistemą į tą pačią duomenų bazę, į kurią eina verslo duomenys. Šis modelis priklauso nuo to, ar pranešimų ir tarpinės programinės įrangos tiekėjas atskleidžia savo saugojimo strategijos detales, kad būtų galima sukonfigūruoti nukreipti į tą pačią duomenų bazę ir prisijungti prie tos pačios operacijos.

Ne visi pardavėjai tai daro lengvai. Alternatyva, kuri tinka beveik bet kuriai duomenų bazei, yra „Apache ActiveMQ“ naudojimas pranešimams siųsti ir atminties strategijos prijungimas prie pranešimų tarpininko. Tai yra gana lengva sukonfigūruoti, kai žinote triuką. Tai parodyta šiame straipsnyje shared-jms-db pavyzdžių projektas. Programos kodui (šiuo atveju bandymai atliekami vienetui) nereikia žinoti, kad šis modelis naudojamas, nes visa tai įgalinta deklaratyviai „Spring“ konfigūracijoje.

Vadinamas bandinio vieneto bandymas „SynchronousMessageTriggerAndRollbackTests“ patikrina, ar viskas veikia sinchroniškai priimant pranešimus. testReceiveMessageUpdateDatabase metodas gauna du pranešimus ir naudoja juos įterpti du įrašus į duomenų bazę. Kai bus baigtas šis metodas, bandymo pagrindas atkuria operaciją, todėl galite patikrinti, ar pranešimai ir duomenų bazės atnaujinimai sugrąžinti, kaip parodyta 3 sąraše:

Sąrašas 3. Pranešimų ir duomenų bazės atnaujinimų tikrinimas

@AfterTransaction public void checkPostConditions () {assertEquals (0, SimpleJdbcTestUtils.countRowsInTable (jdbcTemplate, "T_FOOS")); Sąrašo sąrašas = getMessages (); assertEquals (2, sąrašas.dydis ()); }

Svarbiausios konfigūracijos ypatybės yra „ActiveMQ“ atkaklumo strategija, susiejanti susirašinėjimo sistemą su ta pačia Duomenų šaltinis kaip verslo duomenys ir vėliava ant pavasario „JmsTemplate“ naudojami pranešimams gauti. 4 sąraše parodyta, kaip sukonfigūruoti „ActiveMQ“ patvarumo strategiją:

Sąrašas 4. „ActiveMQ“ patvarumo konfigūravimas

    ...             

5 sąraše rodoma vėliava ant pavasario „JmsTemplate“ kuris naudojamas pranešimams gauti:

Sąrašas 5. Nustatymas „JmsTemplate“ sandorių naudojimui

 ...   

Be sessionTransacted = tiesa, JMS sesijos operacijos API iškvietimai niekada nebus atliekami ir pranešimų priėmimo nebus galima atkurti. Čia svarbūs ingredientai yra įterptasis brokeris su specialiuoju async = klaidinga parametras ir „Windows“ pakuotė Duomenų šaltinis tai kartu užtikrina, kad „ActiveMQ“ naudoja tą patį sandorio JDBC Ryšys kaip Pavasaris.

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