Saya tahu ada pertanyaan serupa di sini, tetapi mereka mengatakan kepada saya untuk kembali ke sistem RDBMS biasa jika saya memerlukan transaksi atau menggunakan operasi atom atau komit dua fase . Solusi kedua sepertinya pilihan terbaik. Yang ketiga saya tidak ingin mengikuti karena tampaknya banyak hal bisa salah dan saya tidak bisa mengujinya di setiap aspek. Saya mengalami kesulitan refactoring proyek saya untuk melakukan operasi atom. Saya tidak tahu apakah ini berasal dari sudut pandang saya yang terbatas (saya hanya bekerja dengan database SQL sejauh ini), atau apakah itu sebenarnya tidak dapat dilakukan.
Kami ingin menguji coba MongoDB di perusahaan kami. Kami telah memilih proyek yang relatif sederhana - SMS gateway. Ini memungkinkan perangkat lunak kami untuk mengirim pesan SMS ke jaringan seluler dan gateway melakukan pekerjaan kotor: benar-benar berkomunikasi dengan penyedia melalui protokol komunikasi yang berbeda. Gateway juga mengelola penagihan pesan. Setiap pelanggan yang mengajukan permohonan layanan harus membeli sejumlah kredit. Sistem secara otomatis mengurangi saldo pengguna ketika pesan dikirim dan menolak akses jika saldo tidak mencukupi. Juga karena kami adalah pelanggan penyedia SMS pihak ketiga, kami mungkin juga memiliki saldo sendiri. Kita harus melacak itu juga.
Saya mulai berpikir tentang bagaimana saya bisa menyimpan data yang diperlukan dengan MongoDB jika saya mengurangi beberapa kerumitan (penagihan eksternal, pengiriman SMS antri). Berasal dari dunia SQL, saya akan membuat tabel terpisah untuk pengguna, satu lagi untuk pesan SMS, dan satu lagi untuk menyimpan transaksi mengenai saldo pengguna. Katakanlah saya membuat koleksi terpisah untuk semua yang ada di MongoDB.
Bayangkan tugas pengiriman SMS dengan langkah-langkah berikut dalam sistem yang disederhanakan ini:
periksa apakah pengguna memiliki saldo yang cukup; tolak akses jika tidak ada kredit yang cukup
kirim dan simpan pesan dalam koleksi SMS dengan perincian dan biaya (dalam sistem siaran langsung pesan akan memiliki
status
atribut dan tugas akan mengambilnya untuk pengiriman dan mengatur harga SMS sesuai dengan keadaan saat ini)mengurangi saldo pengguna dengan biaya pesan yang dikirim
catat transaksi dalam koleksi transaksi
Sekarang apa masalahnya dengan itu? MongoDB dapat melakukan pembaruan atom hanya pada satu dokumen. Dalam aliran sebelumnya, bisa terjadi beberapa jenis kesalahan masuk dan pesan disimpan dalam basis data tetapi saldo pengguna tidak diperbarui dan / atau transaksi tidak dicatat.
Saya datang dengan dua ide:
Buat koleksi tunggal untuk pengguna, dan simpan saldo sebagai bidang, transaksi terkait pengguna dan pesan sebagai sub dokumen dalam dokumen pengguna. Karena kami dapat memperbarui dokumen secara atom, ini sebenarnya memecahkan masalah transaksi. Kekurangan: jika pengguna mengirim banyak pesan SMS, ukuran dokumen bisa menjadi besar dan batas dokumen 4MB dapat tercapai. Mungkin saya bisa membuat dokumen sejarah dalam skenario seperti itu, tapi saya rasa ini bukan ide yang bagus. Saya juga tidak tahu seberapa cepat sistemnya jika saya mendorong lebih banyak data ke dokumen besar yang sama.
Buat satu koleksi untuk pengguna, dan satu untuk transaksi. Ada dua jenis transaksi: pembelian kredit dengan perubahan saldo positif dan pesan yang dikirim dengan perubahan saldo negatif. Transaksi dapat memiliki sub dokumen; misalnya dalam pesan yang dikirim rincian SMS dapat tertanam dalam transaksi. Kekurangan: Saya tidak menyimpan saldo pengguna saat ini jadi saya harus menghitungnya setiap kali pengguna mencoba mengirim pesan untuk memberi tahu apakah pesan itu bisa masuk atau tidak. Saya khawatir perhitungan ini dapat menjadi lambat karena jumlah transaksi yang tersimpan bertambah.
Saya sedikit bingung tentang metode mana yang harus dipilih. Apakah ada solusi lain? Saya tidak dapat menemukan praktik terbaik online tentang cara mengatasi masalah seperti ini. Saya kira banyak programmer yang mencoba mengenal dunia NoSQL menghadapi masalah yang sama pada awalnya.
sumber
Jawaban:
Pada 4.0, MongoDB akan memiliki transaksi multi-dokumen ACID. Rencananya adalah untuk memungkinkan orang-orang dalam penyebaran set replika terlebih dahulu, diikuti oleh kelompok yang terbengkalai. Transaksi dalam MongoDB akan terasa seperti transaksi yang akrab bagi pengembang dari basis data relasional - mereka akan multi-pernyataan, dengan semantik dan sintaksis yang sama (seperti
start_transaction
dancommit_transaction
). Yang penting, perubahan pada MongoDB yang memungkinkan transaksi tidak memengaruhi kinerja untuk beban kerja yang tidak memerlukannya.Untuk lebih jelasnya lihat di sini .
Setelah transaksi terdistribusi, tidak berarti Anda harus memodelkan data Anda seperti di database relasional tabular. Rangkullah kekuatan model dokumen dan ikuti praktik pemodelan data yang baik dan direkomendasikan .
sumber
Hidup Tanpa Transaksi
Transaksi mendukung properti ACID tetapi meskipun tidak ada transaksi
MongoDB
, kami memiliki operasi atom. Nah, operasi atom berarti bahwa ketika Anda mengerjakan satu dokumen, pekerjaan itu akan diselesaikan sebelum orang lain melihat dokumen itu. Mereka akan melihat semua perubahan yang kami lakukan atau tidak satupun dari mereka. Dan menggunakan operasi atom, Anda sering dapat mencapai hal yang sama seperti yang kita lakukan dengan menggunakan transaksi dalam basis data relasional. Dan alasannya adalah bahwa, dalam database relasional, kita perlu membuat perubahan di beberapa tabel. Biasanya tabel yang perlu digabung jadi kami ingin melakukannya sekaligus. Dan untuk melakukannya, karena ada beberapa tabel, kita harus memulai transaksi dan melakukan semua pembaruan itu dan kemudian mengakhiri transaksi. Tetapi denganMongoDB
, kita akan menanamkan data, karena kita akan pra-gabung dalam dokumen dan mereka adalah dokumen kaya yang memiliki hierarki. Kita sering dapat mencapai hal yang sama. Misalnya, dalam contoh blog, jika kami ingin memastikan bahwa kami memperbarui posting blog secara atomis, kami dapat melakukannya karena kami dapat memperbarui seluruh posting blog sekaligus. Sedangkan seolah-olah itu adalah sekelompok tabel relasional, kita mungkin harus membuka transaksi sehingga kita dapat memperbarui koleksi posting dan koleksi komentar.Jadi, apa pendekatan kami yang dapat kami ambil
MongoDB
untuk mengatasi kurangnya transaksi?Update
,findAndModify
,$addToSet
(Dalam update) &$push
(dalam update) operasi beroperasi atom dalam satu dokumen.sumber
Lihat ini , oleh Tokutek. Mereka mengembangkan plugin untuk Mongo yang tidak hanya menjanjikan transaksi tetapi juga meningkatkan kinerja.
sumber
Bawa ke titik: jika integritas transaksional adalah suatu keharusan maka jangan gunakan MongoDB tetapi hanya menggunakan komponen dalam sistem yang mendukung transaksi. Sangat sulit untuk membangun sesuatu di atas komponen untuk menyediakan fungsionalitas yang mirip dengan ACID untuk komponen yang tidak sesuai dengan ACID. Bergantung pada masing-masing penggunaan kata, masuk akal untuk memisahkan tindakan menjadi tindakan transaksional dan non-transaksional dalam beberapa cara ...
sumber
Ini sebenarnya bukan masalah. Kesalahan yang Anda sebutkan adalah kesalahan logis (bug) atau IO (jaringan, kegagalan disk). Kesalahan semacam itu dapat membuat toko transaksi dan transaksi tidak dalam keadaan tidak konsisten. Misalnya, jika sudah mengirim SMS tetapi ketika terjadi kesalahan pesan - tidak dapat mengembalikan pengiriman SMS, yang berarti tidak akan dicatat, keseimbangan pengguna tidak akan berkurang dll.
Masalah sebenarnya di sini adalah pengguna dapat mengambil keuntungan dari kondisi balapan dan mengirim lebih banyak pesan daripada yang dibolehkan keseimbangannya. Ini juga berlaku untuk RDBMS, kecuali jika Anda melakukan pengiriman dalam transaksi SMS dengan penguncian bidang saldo (yang akan menjadi hambatan besar). Sebagai solusi yang mungkin untuk MongoDB akan menggunakan
findAndModify
pertama untuk mengurangi saldo dan memeriksanya, jika negatif melarang pengiriman dan kembalikan jumlahnya (kenaikan atom). Jika positif, terus mengirim dan jika gagal mengembalikan jumlah. Pengumpulan riwayat saldo juga dapat dipertahankan untuk membantu memperbaiki / memverifikasi bidang keseimbangan.sumber
Proyek ini sederhana, tetapi Anda harus mendukung transaksi pembayaran, yang membuat semuanya menjadi sulit. Jadi, misalnya, sistem portal yang kompleks dengan ratusan koleksi (forum, obrolan, iklan, dll ...) dalam beberapa hal lebih sederhana, karena jika Anda kehilangan entri forum atau obrolan, tidak ada yang benar-benar peduli. Jika Anda, di sisi lain, kehilangan transaksi pembayaran yang merupakan masalah serius.
Jadi, jika Anda benar-benar ingin proyek percontohan untuk MongoDB, memilih salah satu yang sederhana dalam bahwa rasa hormat.
sumber
Transaksi tidak ada dalam MongoDB untuk alasan yang sah. Ini adalah salah satu hal yang membuat MongoDB lebih cepat.
Dalam kasus Anda, jika transaksi adalah suatu keharusan, mongo sepertinya tidak cocok.
Mungkin RDMBS + MongoDB, tetapi itu akan menambah kerumitan dan akan membuatnya lebih sulit untuk mengelola dan mendukung aplikasi.
sumber
Ini mungkin blog terbaik yang saya temukan tentang menerapkan fitur transaksi seperti untuk mongodb.!
Menyinkronkan Bendera: terbaik untuk hanya menyalin data dari dokumen master
Antrian Pekerjaan: tujuan umum, menyelesaikan 95% kasus. Sebagian besar sistem perlu memiliki setidaknya satu antrian pekerjaan!
Two Phase Commit: teknik ini memastikan bahwa setiap entitas selalu memiliki semua informasi yang diperlukan untuk mencapai kondisi yang konsisten
Rekonsiliasi Log: teknik yang paling kuat, ideal untuk sistem keuangan
Versi: menyediakan isolasi dan mendukung struktur yang kompleks
Baca ini untuk info lebih lanjut: https://dzone.com/articles/how-implement-robust-and
sumber
Ini sudah terlambat tetapi berpikir ini akan membantu di masa depan. Saya menggunakan Redis untuk membuat antrian untuk menyelesaikan masalah ini.
Persyaratan:
Gambar di bawah ini menunjukkan 2 tindakan perlu dijalankan bersamaan tetapi fase 2 dan fase 3 tindakan 1 harus diselesaikan sebelum memulai fase 2 tindakan 2 atau berlawanan (Fase dapat berupa permintaan REST api, permintaan basis data, atau jalankan kode javascript ... ).
Bagaimana antrian membantu Anda
Mengantri memastikan bahwa setiap kode blok antara
lock()
danrelease()
dalam banyak fungsi tidak akan berjalan sebagai waktu yang sama, buat mereka mengisolasi.Bagaimana membangun antrian
Saya hanya akan fokus pada bagaimana menghindari bagian kondisi lomba ketika membangun antrian di situs backend. Jika Anda tidak tahu ide dasar antrian, datang ke sini .
Kode di bawah ini hanya menunjukkan konsep, Anda perlu menerapkan dengan cara yang benar.
Tetapi Anda perlu
isRunning()
setStateToRelease()
setStateToRunning()
mengisolasinya sendiri atau Anda menghadapi kondisi balapan lagi. Untuk melakukan ini saya memilih Redis untuk tujuan ACID dan scalable.Redis dokumen berbicara tentang transaksi itu:
P / s:
Saya menggunakan Redis karena layanan saya sudah menggunakannya, Anda dapat menggunakan isolasi dukungan cara lain untuk melakukan itu.
Di
action_domain
dalam kode saya di atas untuk ketika Anda hanya perlu tindakan 1 panggilan oleh pengguna A memblokir tindakan 2 dari pengguna A, jangan memblokir pengguna lain. Idenya adalah meletakkan kunci unik untuk mengunci setiap pengguna.sumber
Transaksi tersedia sekarang di MongoDB 4.0. Contoh di sini
sumber