Mă întreb dacă există o modalitate de a face apeluri asincrone la o bază de date?
De exemplu, imaginați-vă că m-am'am o mare rugaminte, care ia foarte mult timp pentru a procesa, vreau să trimit cerere și de a primi o notificare atunci când cererea va returna o valoare (prin trecerea unui Ascultător/apel invers sau ceva de genul). Eu nu't doriți să blocați de așteptare pentru baza de date pentru a răspunde.
Eu nu't consideră că, folosind un pool de thread-uri este o soluție pentru că nu't scară, în caz de grele cereri concurente acest lucru va genera un număr foarte mare de fire.
Ne confruntăm cu acest tip de problemă cu servere de rețea și trebuie găsite soluții prin utilizarea selecta/sondaj/epoll apel de sistem pentru a evita un fir de pe conexiune. Am'm întrebam cum de a avea o caracteristică similară cu baza de date cerere?
Notă: Am'm conștienți de faptul că, folosind un FixedThreadPool poate fi un lucru bun, dar nu'm-a surprins că nimeni nu a dezvoltat un sistem foarte asincron (fără utilizarea de fir suplimentar).
Update Din cauza de lipsa de soluții practice, am decis pentru a crea o bibliotecă (parte a învârti) eu: învârti-mysql. Practic decodează/decodează mysql cerere/răspuns, și de a folosi Învârti/Netty sub capota. O cântare extrem de bine chiar și cu un număr mare de conexiuni.
Eu nu't înțeleg cum a propus abordări care încheia apelurile JDBC în Actori, executori judecătorești sau orice altceva vă poate ajuta aici - poate cineva clarifica.
Cu siguranță, problema de bază este că JDBC operațiuni bloc de pe soclu IO. Atunci când ea face acest lucru blochează Firul rulează pe - end de poveste. Orice ambalaj cadru alegeți să utilizați de gând să se încheie cu un fir de a fi ocupat/blocat pe cerere concurente.
Dacă de fond al sistemului drivere de baze de date (MySql?) oferă un mijloc de a intercepta priza de creație (a se vedea SocketFactory) apoi am imagina că ar fi posibil să se construiască un eveniment asincron condus de baze de date strat pe partea de sus a JDBC api dar am'de a îngloba întreaga JDBC în spatele unui eveniment condus de fatada, iar fațada nu't arata ca JDBC (după ce ar fi determinate de un eveniment). De procesare de date s-ar întâmpla asincron pe un alt thread pentru a apelantului, și te'd trebuie să lucreze cum de a construi un manager de tranzacții care nu't se bazează pe fir de afinitate.
Ceva de genul abordare-am spus ar permite chiar și un singur fir de fundal pentru a procesa o sarcină de concurente JDBC exec's. În practică,'d alerga, probabil, o piscină de fire pentru a face uz de mai multe nuclee.
(Desigur, am'm nu comentând cu privire la logica de întrebarea inițială doar răspunsuri care implică faptul de concurenta intr-un scenariu cu blocarea socket IO este posibil fără ca utilizatorul de un selector model mai simplu să-ți tipic JDBC concurenta și a pus într-o legătură exterioară de mărimea potrivită).
Se pare ca MySql, probabil, are ceva de-a lungul liniilor I'm sugerând --- http://code.google.com/p/async-mysql-connector/wiki/UsageExample
L's imposibil de a face un apel asincron la baza de date prin intermediul JDBC, dar puteți face apeluri asincrone să JDBC cu Actori (de exemplu, actorul face apeluri la PB prin intermediul JDBC, și trimite mesaje de la terțe părți, atunci când apelurile sunt peste), sau, dacă vă place CPS, cu asamblare futures (promisiuni) (o bună punere în aplicare este Scalaz Promisiunile)
nu't consideră că, folosind un pool de thread-uri este o soluție pentru că nu't scară, în caz de grele cereri concurente acest lucru va genera un număr foarte mare de fire.
Scala actori implicit sunt bazate pe evenimente (nu thread-based) - continuarea programarea permite crearea de milioane de actori pe un standard de JVM setup.
Daca're direcționare Java, Akka Cadru este un Actor model de implementare care are o bună API atât pentru Java și Scala.
În afară de asta, sincron natura JDBC face sens perfect pentru mine. Costul unei baze de date sesiune este mult mai mare decât costul de Java firul fiind blocat (fie în prim - plan sau de fundal) și de așteptare pentru un răspuns. Dacă întrebările dumneavoastră rula atât de mult, încât capacitățile de un executor serviciu (sau de ambalaj Actor/fork-join/promit concurenta cadre) nu sunt suficiente pentru tine (și tu're consuma prea multe fire) ar trebui mai întâi de toate cred despre dvs. de sarcină de bază de date. În mod normal, ca răspuns la o bază de date se întoarce foarte repede, și un executor serviciul susținută cu un fix thread pool este o soluție destul de bună. Dacă aveți prea multe interogări de lungă durată, ar trebui să ia în considerare în avans (pre-)prelucrare - ca noapte de noapte recalcularea datelor sau ceva de genul asta.
Poate că ai putea folosi un JMS asincron sistem de mesagerie, care cântare destul de bine, IMHO:
Trimite un mesaj la o listă de Așteptare, în cazul în care abonații vor accepta mesajul, și executați SQL proces. Ta principală va continua procesul de funcționare și de a accepta sau de a trimite cereri noi.
Atunci când SQL procesul se termină, puteți rula în sens invers: trimite un mesaj la un ResponseQueue cu rezultatul procesului, și un ascultător pe partea de client accepta si executa codul de apel invers.
Nu există nici un sprijin direct în JDBC dar aveți mai multe opțiuni, cum ar fi MDB, Executorii de Java 5.
"nu't consideră că, folosind un pool de thread-uri este o soluție pentru că nu't scară, în caz de grele cereri concurente acest lucru va genera un număr foarte mare de fire."
Sunt curios de ce ar fi o piscină mărginită de fire nu este de gând să scară? Este o piscina nu este thread-per-cerere să ruleze un fir pe fiecare cerere. Am fost folosind acest lucru pentru destul de cândva pe o sarcină grea webapp și nu am văzut nici o probleme pana acum.
Așa cum am menționat în alte răspunsuri JDBC API nu este Asincron prin natura sa. Cu toate acestea, dacă poți trăi cu un subset al operațiilor și un API diferit există soluții. Un exemplu este https://github.com/jasync-sql/jasync-sql care lucrează pentru MySQL și PostgreSQL.
O soluție este în curs de dezvoltate pentru a face reactive de conectivitate posibil, cu standard de baze de date relaționale.
Oameni care doresc să scară păstrând în același timp utilizarea de baze de date relaționale sunt tăiate de programare reactiv datorită existente, pe baza standardelor de pe de blocare I/O. R2DBC specifică un nou API care permite reactive cod care lucra eficient cu baze de date relaționale.
R2DBC este o specificație proiectat de la sol pentru reactivă programare cu baze de date SQL definirea unui non-blocare pentru SPI driver de baze de date implementatori și client library autori. R2DBC drivere pune în aplicare pe deplin la baza de date sârmă protocolului pe partea de sus de un non-blocare I/O strat.
O întrebare veche, dar unele mai multe informații. Nu este posibil de a avea JDBC problema asincron cereri la baza de date în sine, dacă un furnizor oferă o extensie a JDBC și un înveliș să se ocupe cu JDBC. Asta a spus, este posibil să-și încheie JDBC în sine, cu o prelucrare coadă, și să pună în aplicare logica care poate procesa pe coadă pe una sau mai multe conexiuni separate. Un avantaj al acestei pentru anumite tipuri de apeluri este că logica, dacă, în destul de grea sarcină, ar putea converti toate apelurile într-JDBC loturi de prelucrare, care poate accelera logica semnificativ. Asta este cea mai utilă pentru apeluri în cazul în care datele sunt introduse, și rezultatul efectiv trebuie doar să fie conectat, dacă există o eroare. Un bun exemplu de acest lucru este în cazul insertii sunt efectuate pentru a vă conecta activitatea utilizatorului. Aplicația a câștigat't pasă dacă apelul completeaza imediat sau în câteva secunde.
Ca o paranteză, un singur produs pe piață oferă o politică bazată pe abordarea de a permite apeluri asincrone ca cei care am descris-o fi făcut în mod asincron (http://www.heimdalldata.com/). Disclaimer: eu sunt co-fondator al companiei. Acesta vă permite expresii regulate pentru a fi aplicate pentru transformarea datelor de cereri, cum ar fi insert/update/sterge pentru orice JDBC sursă de date, și în mod automat, lot-le împreună pentru prelucrare. Atunci când este utilizat cu MySQL și rewriteBatchedStatements opțiune (https://stackoverflow.com/questions/26307760/mysql-and-jdbc-with-rewritebatchedstatements-true) acest lucru poate reduce semnificativ generală a încărca în baza de date.
Ai trei optiuni in opinia mea:
Diclaimer: eu sunt unul dintre dezvoltatorii de CoralMQ.
Aici este o schiță despre ce este un non-blocare jdbc api ar putea arata ca de la Oracle a prezentat la JavaOne: https://static.rainfocus.com/oracle/oow16/sess/1461693351182001EmRq/ppt/CONF1578%2020160916.pdf
Deci, se pare că, în sfârșit, cu adevărat asincron JDBC apelurile vor fi într-adevăr posibil.
De Java 5.0 executorii ar putea veni la îndemână.
Puteți avea un număr fix de fire să se ocupe de operațiuni de lungă de funcționare. Și în loc de Runnable
poti folosi Nevărsat
, care returnează un rezultat. Rezultatul este încapsulat într-o Viitor<ReturnType>
obiect, astfel încât să puteți obține atunci când s-a întors.
Mă gândeam idei aici. De ce n't ai un pool de conexiuni la baza de date cu fiecare având un fir. Fiecare fir are acces la o coadă. Atunci când vrei să faci o interogare care să ia o lungă perioadă de timp, puteți pune pe coadă și apoi unul din fire se va ridica și-l ocupe. Tu nu va avea prea multe fire pentru că numărul de fire sunt delimitate.
Edit: Sau mai bine încă, doar un număr de fire. Atunci când un fir vede ceva într-o coadă, se cere o conexiune de la piscină și se ocupă de el.
Camera comunelor-dbutils biblioteca are suport pentru o AsyncQueryRunner
care vă oferă o `ExecutorService să și-l întoarce un "Viitor". Merită verificat ca acesta's simplu de utilizat și să se asigure că ai câștigat't scurgere de resurse.
Dacă sunteți interesat în asincron de date Api-uri pentru Java ar trebui să știi că există o nouă inițiativă de a veni cu un set de Api-uri standard, bazat pe CompletableFuture și lambda. Există, de asemenea, o punere în aplicare a acestor Api-uri peste JDBC care poate fi folosit pentru a practica aceste Api-uri: https://github.com/oracle/oracle-db-examples/tree/master/java/AoJ JavaDoc este menționat în README de proiect github.