Saya ingin tahu apakah ada cara untuk melakukan panggilan asinkron ke database?
Misalnya, bayangkan saya memiliki permintaan besar yang membutuhkan waktu sangat lama untuk diproses, saya ingin mengirim permintaan dan menerima pemberitahuan ketika permintaan akan mengembalikan nilai (dengan melewati Pendengar / panggilan balik atau sesuatu). Saya tidak ingin memblokir menunggu database untuk menjawab.
Saya tidak menganggap bahwa menggunakan kumpulan thread adalah solusi karena tidak skala, dalam kasus permintaan bersamaan yang berat ini akan menelurkan sejumlah besar thread.
Kami menghadapi masalah semacam ini dengan server jaringan dan kami telah menemukan solusi dengan menggunakan panggilan sistem select / poll / epoll untuk menghindari satu utas per koneksi. Saya hanya ingin tahu bagaimana caranya memiliki fitur yang mirip dengan permintaan basis data?
Catatan: Saya sadar bahwa menggunakan FixedThreadPool mungkin merupakan solusi yang baik, tetapi saya terkejut bahwa tidak ada yang mengembangkan sistem yang benar-benar tidak sinkron (tanpa menggunakan utas tambahan).
Pembaruan ** **
Karena kurangnya solusi praktis nyata, saya memutuskan untuk membuat perpustakaan (bagian dari finagle) sendiri: finagle-mysql . Ini pada dasarnya menerjemahkan / menerjemahkan permintaan / respons mysql, dan menggunakan Finagle / Netty di bawah tenda. Ini berskala sangat baik bahkan dengan sejumlah besar koneksi.
sumber
Jawaban:
Saya tidak mengerti bagaimana salah satu pendekatan yang diusulkan yang membungkus panggilan JDBC di Aktor, pelaksana atau apa pun dapat membantu di sini - dapat seseorang mengklarifikasi.
Tentunya masalah dasarnya adalah bahwa operasi JDBC memblokir IO pada soket. Ketika hal ini terjadi, ia memblokir Thread yang berjalan di akhir cerita. Apapun kerangka pembungkus yang Anda pilih akan berakhir dengan satu utas tetap sibuk / diblokir per permintaan bersamaan.
Jika driver basis data yang mendasarinya (MySql?) Menawarkan cara untuk mencegat pembuatan soket (lihat SocketFactory) maka saya membayangkan akan mungkin untuk membangun lapisan basis data yang didorong oleh peristiwa async di atas api JDBC tetapi kita harus merangkum seluruh JDBC di belakang fasad yang digerakkan oleh acara, dan fasad yang tidak akan terlihat seperti JDBC (setelah itu akan digerakkan oleh acara). Pemrosesan basis data akan terjadi secara async pada utas yang berbeda dengan penelepon, dan Anda harus mengetahui cara membangun manajer transaksi yang tidak bergantung pada afinitas utas.
Sesuatu seperti pendekatan yang saya sebutkan akan memungkinkan bahkan utas latar belakang tunggal untuk memproses beban bersamaan JDBC exec. Dalam praktiknya, Anda mungkin akan menjalankan kumpulan utas untuk memanfaatkan beberapa inti.
(Tentu saja saya tidak mengomentari logika pertanyaan asli hanya tanggapan yang menyiratkan bahwa konkurensi dalam skenario dengan memblokir soket IO dimungkinkan tanpa pengguna pola pemilih - lebih sederhana hanya untuk bekerja di luar konkurensi JDBC khas Anda dan menempatkan di kolam koneksi dengan ukuran yang tepat).
Sepertinya MySql mungkin melakukan sesuatu yang saya sarankan --- http://code.google.com/p/async-mysql-connector/wiki/UsageExample
sumber
Tidak mungkin membuat panggilan asinkron ke database melalui JDBC, tetapi Anda dapat membuat panggilan asinkron ke JDBC dengan Aktor (mis. Aktor membuat panggilan ke DB melalui JDBC, dan mengirim pesan ke pihak ketiga, saat panggilan selesai), atau, jika Anda menyukai CPS, dengan futures pipelined (janji) (implementasi yang baik adalah Scalaz Promises )
Aktor scala secara default berbasis pada peristiwa (bukan berdasarkan thread) - penjadwalan lanjutan memungkinkan pembuatan jutaan aktor pada pengaturan JVM standar.
Jika Anda menargetkan Java, Akka Framework adalah implementasi model Aktor yang memiliki API yang baik untuk Java dan Scala.
Selain itu, sifat sinkron JDBC sangat masuk akal bagi saya. Biaya sesi basis data jauh lebih tinggi daripada biaya utas Java yang diblokir (baik di latar depan atau di belakang) dan menunggu tanggapan. Jika pertanyaan Anda berjalan begitu lama sehingga kemampuan layanan pelaksana (atau membungkus kerangka kerja konkurensi Actor / fork-join / janji) tidak cukup untuk Anda (dan Anda menggunakan terlalu banyak utas), pertama-tama Anda harus memikirkan tentang beban basis data. Biasanya respons dari basis data kembali sangat cepat, dan layanan pelaksana yang didukung dengan kumpulan utas tetap merupakan solusi yang cukup baik. Jika Anda memiliki terlalu banyak pertanyaan yang berjalan lama, Anda harus mempertimbangkan pemrosesan di muka (pra-) - seperti perhitungan ulang malam hari dari data atau sesuatu seperti itu.
sumber
Mungkin Anda bisa menggunakan sistem pesan asinkron JMS, yang berskala cukup baik, IMHO:
Kirim pesan ke Antrian, di mana pelanggan akan menerima pesan, dan jalankan proses SQL. Proses utama Anda akan terus berjalan dan menerima atau mengirim permintaan baru.
Ketika proses SQL berakhir, Anda dapat menjalankan sebaliknya: mengirim pesan ke ResponseQueue dengan hasil dari proses, dan pendengar di sisi klien menerimanya dan menjalankan kode panggilan balik.
sumber
Tidak ada dukungan langsung di JDBC tetapi Anda memiliki beberapa opsi seperti MDB, Pelaksana dari Java 5.
"Saya tidak menganggap bahwa menggunakan kumpulan utas adalah solusi karena tidak menskalakan, dalam kasus permintaan serentak yang besar ini akan menelurkan sejumlah besar utas."
Saya ingin tahu mengapa kumpulan benang yang dibatasi tidak akan bertambah? Ini bukan kumpulan utas per permintaan untuk menelurkan utas per setiap permintaan. Saya telah menggunakan ini selama beberapa waktu di webapp beban berat dan kami belum melihat masalah sejauh ini.
sumber
Sepertinya API jdbc asynchronous baru "JDBC next" sedang bekerja.
Lihat presentasi di sini
Anda dapat mengunduh API dari sini
sumber
Seperti yang disebutkan dalam jawaban lain, JDBC API pada dasarnya bukan Async.
Namun, jika Anda dapat hidup dengan subset operasi dan API yang berbeda ada solusinya. Salah satu contohnya adalah https://github.com/jasync-sql/jasync-sql yang berfungsi untuk MySQL dan PostgreSQL.
sumber
Proyek Ajdbc tampaknya menjawab masalah ini http://code.google.com/p/adbcj/
Saat ini ada 2 driver async asli eksperimental untuk mysql dan postgresql.
sumber
Sebuah pertanyaan lama, tetapi beberapa informasi lebih lanjut. Tidak mungkin memiliki JDBC mengeluarkan permintaan asinkron ke database itu sendiri, kecuali jika vendor memberikan ekstensi ke JDBC dan pembungkus untuk menangani JDBC. Yang mengatakan, adalah mungkin untuk membungkus JDBC itu sendiri dengan antrian pemrosesan, dan untuk mengimplementasikan logika yang dapat memproses dari antrian pada satu atau lebih koneksi terpisah. Satu keuntungan dari ini untuk beberapa jenis panggilan adalah bahwa logika, jika di bawah beban yang cukup berat, dapat mengubah panggilan menjadi batch JDBC untuk diproses, yang dapat mempercepat logika secara signifikan. Ini paling berguna untuk panggilan di mana data dimasukkan, dan hasil aktual hanya perlu dicatat jika ada kesalahan. Contoh yang bagus tentang ini adalah jika memasukkan dilakukan untuk mencatat aktivitas pengguna. Aplikasi menang '
Sebagai catatan tambahan, satu produk di pasar menyediakan pendekatan yang didorong oleh kebijakan untuk memungkinkan panggilan asinkron seperti yang saya jelaskan dibuat secara tidak sinkron ( http://www.heimdalldata.com/ ). Penafian: Saya adalah salah satu pendiri perusahaan ini. Ini memungkinkan ekspresi reguler untuk diterapkan pada permintaan transformasi data seperti memasukkan / memperbarui / menghapus sumber data JDBC, dan secara otomatis akan mengumpulkannya bersama untuk diproses. Ketika digunakan dengan MySQL dan opsi rewriteBatchedStatements ( MySQL dan JDBC dengan rewriteBatchedStatements = true ) ini dapat secara signifikan menurunkan keseluruhan beban pada database.
sumber
Anda memiliki tiga opsi menurut saya:
Diclaimer: Saya adalah salah satu pengembang CoralMQ.
sumber
Sebuah solusi sedang dikembangkan untuk memungkinkan konektivitas reaktif dengan database relasional standar.
WebDite R2DBC
GitHub R2DBC
Matriks Fitur
sumber
Para pelaksana Java 5.0 mungkin berguna.
Anda dapat memiliki sejumlah utas untuk menangani operasi yang sudah berjalan lama. Dan alih-alih
Runnable
Anda dapat menggunakanCallable
, yang mengembalikan hasil. Hasilnya diringkas dalam suatuFuture<ReturnType>
objek, sehingga Anda bisa mendapatkannya ketika itu kembali.sumber
Berikut adalah garis besar tentang bagaimana api jdbc non-blocking dapat terlihat dari Oracle yang disajikan di JavaOne: https://static.rainfocus.com/oracle/oow16/sess/1461693351182001EmRq/ppt/CONF1578%2020160916.pdf
Jadi sepertinya pada akhirnya, panggilan JDBC yang benar-benar tidak sinkron memang akan mungkin.
sumber
Hanya ide gila: Anda bisa menggunakan pola Iteratee di atas hasil JBDC. Setel dalam beberapa Future / Promise
Hammersmith melakukan itu untuk MongoDB .
sumber
Saya hanya memikirkan ide di sini. Mengapa Anda tidak dapat memiliki kumpulan koneksi database dengan masing-masing memiliki utas. Setiap utas memiliki akses ke antrian. Saat Anda ingin melakukan kueri yang membutuhkan waktu lama, Anda dapat memasukkan antrian dan kemudian salah satu utas akan mengambilnya dan menanganinya. Anda tidak akan pernah memiliki terlalu banyak utas karena jumlah utas Anda dibatasi.
Sunting: Atau lebih baik lagi, hanya sejumlah utas. Ketika utas melihat sesuatu dalam antrian, ia meminta koneksi dari kolam dan menanganinya.
sumber
Pustaka commons-dbutils memiliki dukungan untuk
AsyncQueryRunner
mana Anda memberikanExecutorService
dan mengembalikan aFuture
. Layak dicoba karena mudah digunakan dan memastikan Anda tidak akan membocorkan sumber daya.sumber
Jika Anda tertarik pada API database asinkron untuk Java, Anda harus tahu bahwa ada inisiatif baru untuk menghasilkan seperangkat API standar berdasarkan CompletableFuture dan lambdas. Ada juga implementasi API ini di atas JDBC yang dapat digunakan untuk mempraktekkan API ini: https://github.com/oracle/oracle-db-examples/tree/master/java/AoJ JavaDoc disebutkan dalam README of proyek github.
sumber