Ada banyak solusi yang lebih mudah dikompromikan daripada yang nyaman bagi saya. Memang, jika use case Anda rumit, seperti memindahkan uang antar bank yang berbeda, alternatif yang lebih menyenangkan mungkin tidak mungkin. Tapi mari kita lihat apa yang bisa kita lakukan dalam skenario umum, di mana penggunaan layanan microser mengganggu transaksi basis data calon kami.
Opsi 1: Hindari kebutuhan transaksi jika semuanya memungkinkan
Jelas dan disebutkan sebelumnya, tetapi ideal jika kita bisa mengelolanya. Apakah komponen-komponen tersebut sebenarnya termasuk dalam microservice yang sama? Atau bisakah kita mendesain ulang sistem sehingga transaksi menjadi tidak perlu? Mungkin menerima non-transaksionalitas adalah pengorbanan yang paling terjangkau.
Opsi 2: Gunakan antrian
Jika ada cukup kepastian bahwa layanan lain akan berhasil pada apa pun yang kita inginkan, kita dapat memanggilnya melalui beberapa bentuk antrian. Item yang antri tidak akan diambil hingga nanti, tetapi kami dapat memastikan bahwa item tersebut sudah antri .
Misalnya, katakan bahwa kami ingin memasukkan entitas dan mengirim email, sebagai satu transaksi. Alih-alih memanggil server surat, kami mengantri e-mail dalam sebuah tabel.
Begin transaction
Insert entity
Insert e-mail
Commit transaction
Kelemahan yang jelas adalah bahwa beberapa layanan microser akan membutuhkan akses ke tabel yang sama.
Opsi 3: Lakukan pekerjaan eksternal yang terakhir, sesaat sebelum menyelesaikan transaksi
Pendekatan ini bertumpu pada asumsi bahwa melakukan transaksi sangat tidak mungkin gagal.
Begin transaction
Insert entity
Insert another entity
Make external call
Commit transaction
Jika kueri gagal, panggilan eksternal belum terjadi. Jika panggilan eksternal gagal, transaksi tidak pernah dilakukan.
Pendekatan ini hadir dengan keterbatasan yang kita hanya bisa membuat satu panggilan eksternal, dan itu harus dilakukan terakhir (yaitu kita tidak dapat menggunakan hasilnya dalam permintaan kita).
Opsi 4: Buat sesuatu dalam status tertunda
Seperti yang diposting di sini , kami dapat meminta beberapa layanan microser membuat komponen yang berbeda, masing-masing dalam status tertunda, non-transaksi.
Validasi apa pun dilakukan, tetapi tidak ada yang dibuat dalam keadaan definitif. Setelah semuanya berhasil dibuat, masing-masing komponen diaktifkan. Biasanya, operasi ini sangat sederhana dan kemungkinan kesalahan terjadi sangat kecil, sehingga kita bahkan dapat memilih untuk melakukan aktivasi secara non-transaksi.
Kelemahan terbesarnya adalah kita harus memperhitungkan keberadaan barang-barang yang tertunda. Permintaan pilih apa pun perlu mempertimbangkan apakah akan memasukkan data yang tertunda. Sebagian besar harus mengabaikannya. Dan pembaruan adalah cerita lain sama sekali.
Opsi 5: Biarkan microservice membagikan kuerinya
Tidak ada opsi lain yang melakukannya untuk Anda? Kalau begitu mari kita menjadi ortodoks .
Tergantung pada perusahaan, yang ini mungkin tidak dapat diterima. Aku sadar. Ini tidak lazim. Jika tidak dapat diterima, pilih rute lain. Tetapi jika ini cocok dengan situasi Anda, itu menyelesaikan masalah dengan sederhana dan kuat. Mungkin saja kompromi yang paling dapat diterima.
Ada cara untuk mengubah kueri dari beberapa layanan mikro menjadi transaksi basis data tunggal yang sederhana.
Kembalikan kueri, alih-alih menjalankannya.
Begin transaction
Execute our own query
Make external call, receiving a query
Execute received query
Commit transaction
Dari sisi jaringan, setiap layanan mikro harus dapat mengakses setiap basis data. Ingatlah hal ini, juga dalam hal penskalaan di masa depan.
Jika database yang terlibat dalam transaksi berada di server yang sama, ini akan menjadi transaksi reguler. Jika mereka berada di server yang berbeda, itu akan menjadi transaksi terdistribusi. Kode tetap sama.
Kami menerima permintaan, termasuk jenis koneksinya, parameternya, dan string koneksinya. Kita dapat membungkusnya dalam kelas Command yang dapat dieksekusi dengan rapi, menjaga alirannya tetap terbaca: Panggilan layanan microser di dalam Command, yang kita jalankan, sebagai bagian dari transaksi kami.
String koneksi adalah apa yang diberikan microservice asal, sehingga untuk semua maksud dan tujuan, kueri masih dianggap dijalankan oleh microservice itu. Kami hanya merutekannya secara fisik melalui microservice klien. Apakah itu membuat perbedaan? Yah, itu memungkinkan kita memasukkannya ke dalam transaksi yang sama dengan permintaan lain.
Jika kompromi dapat diterima, pendekatan ini memberi kita transaksionalitas langsung dari aplikasi monolith, dalam arsitektur layanan-mikro.