Rakan-rakan kita sepatutnya sudah cukup mendengar tentang mesej, Rocket MQ. Faedah memperkenalkan perisian tengah boleh memainkan peranan dalam menentang konkurensi tinggi, memuncak, dan penyahgandingan perniagaan.
Seperti yang ditunjukkan di atas:
(1) Perkhidmatan pesanan menghantar mesej kepada middleware MQ (2) Perkhidmatan logistik memantau mesej middleware MQ untuk penggunaan
Mari kita bincangkan dalam artikel ini bagaimana untuk memastikan perkhidmatan pesanan Mesej berjaya dihantar ke perisian tengah MQ, mengambil RabbitMQ sebagai contoh.
Rakan-rakan saya mungkin mempunyai beberapa soalan tentang ini Jika perkhidmatan pesanan memulakan perkhidmatan mesej, bukankah ia bermakna kejayaan jika pemulangan berjaya? Contohnya, kod pseudo berikut:
Dalam kod di atas, mesej biasanya dihantar seperti ini. Adakah anda fikir terdapat sebarang masalah?
Mari kita bincangkan tentang senario di bawah Apakah yang akan berlaku jika pelayan MQ tiba-tiba down? Adakah semua mesej yang dihantar oleh perkhidmatan pesanan kami hilang? Ya, secara amnya perisian tengah MQ akan menyimpan mesej dalam ingatan untuk meningkatkan daya pemprosesan sistem Jika tiada pemprosesan lain dilakukan, apabila pelayan MQ terputus, semua mesej akan hilang. Ini tidak dibenarkan oleh perniagaan dan akan menyebabkan kesan yang besar.
Kawan-kawan yang berpengalaman akan berkata, saya tahu satu cara adalah dengan meneruskan mesej semasa menghantar mesej dalam RabbitMQ, akan ada parameter tahan lama yang boleh ditetapkan , ia akan Kegigihan.
Dalam kes ini, walaupun pelayan MQ turun, mesej akan disimpan dalam fail cakera selepas dimulakan semula, jadi ia tidak akan hilang. Ya, ini memastikan bahawa mesej tidak akan hilang dengan kebarangkalian tertentu.
Tetapi akan berlaku senario di mana mesej itu baru sahaja disimpan ke memori MQ, tetapi sebelum sempat dikemas kini ke fail cakera, ia tiba-tiba ranap. (Sial, ini akan berlaku dalam tempoh yang singkat. Kebarangkalian terlalu rendah.) Senario ini akan menjadi sangat biasa dalam proses penghantaran mesej berskala besar yang berterusan.
Apa yang perlu dilakukan? Bagaimanakah kita boleh memastikan bahawa ia akan berterusan ke cakera?
Masalah di atas timbul kerana tiada siapa yang memberitahu kita sama ada kegigihan berjaya. Nasib baik, banyak MQ mempunyai ciri pemberitahuan panggil balik dan RabbitMQ mempunyai mekanisme pengesahan untuk memberitahu kami sama ada kegigihan berjaya?
Prinsip mekanisme pengesahan:
(1) Penerbit mesej menghantar mesej kepada MQ Jika penerimaan berjaya, MQ akan mengembalikan mesej ack kepada penerbit
(2) Jika penerimaan mesej tidak berjaya, MQ A nack message akan dikembalikan kepada producer
Pseudocode di atas mempunyai dua cara untuk memproses mesej, iaitu ack callback dan nack callback.
Adakah ini memastikan 100% mesej tidak akan hilang?
Mari kita lihat mekanisme pengesahan. Bayangkan jika setiap kali pengeluar kita menghantar mesej, MQ mesti diteruskan ke cakera, dan kemudian memulakan panggilan balik ack atau nack. Dalam kes ini, daya pemprosesan MQ kami adalah sangat rendah, kerana mesej mesti diteruskan ke cakera setiap kali. Menulis ke cakera adalah sangat perlahan. Ini tidak boleh diterima dalam senario konkurensi tinggi, dan daya pengeluaran terlalu rendah.
Jadi pelaksanaan sebenar cakera berterusan MQ diproses melalui panggilan tak segerak. Contohnya, apabila terdapat beribu-ribu mesej, ia akan dibuang ke cakera sekali gus. Daripada mengepam cakera setiap kali mesej datang.
Jadi mekanisme comfirm sebenarnya adalah mekanisme dengar tak segerak, iaitu untuk memastikan throughput sistem yang tinggi Ini bermakna ia masih tidak 100% dijamin mesej tidak akan hilang, kerana walaupun mekanisme pengesahan ditambah. , mesej masih dalam memori MQ Komputer ranap tanpa berkelip ke cakera, dan ia masih tidak dapat ditangani.
Selepas berkata begitu banyak, saya masih tidak dapat menjaminnya, jadi apa yang perlu saya lakukan? ? ?
Malah, sebab pentingnya adalah mustahil untuk menentukan sama ada ia berterusan? Jadi bolehkah kita membuat mesej itu berterusan sendiri? Jawapannya ya, rancangan kami akan berkembang lebih jauh.
Proses dalam gambar di atas:
(1) Sebelum menghantar mesej, pengeluar perkhidmatan pesanan terlebih dahulu meneruskan mesej kepada Redis atau DB disyorkan untuk prestasi tinggi. Status mesej ialah Menghantar.
(2) Adakah mesej pemantauan mekanisme pengesahan berjaya dihantar? Jika ack berjaya, padamkan mesej ini dalam Redis.
(3) Jika nack gagal, anda boleh memilih sama ada untuk menghantar semula mesej mengikut perniagaan anda sendiri. Anda juga boleh memadamkan mesej ini, bergantung pada keputusan perniagaan anda.
(4) Tugas berjadual ditambahkan di sini untuk menarik mesej selepas tempoh masa tertentu Status mesej masih dihantar Status ini menunjukkan bahawa perkhidmatan pesanan belum menerima mesej kejayaan ack.
(5) Tugas berjadual akan menyampaikan mesej pampasan. Pada masa ini, jika ack panggil balik MQ berjaya diterima, mesej akan dipadamkan dalam Redis.
Mekanisme ini sebenarnya adalah mekanisme pampasan Saya tidak kisah sama ada MQ benar-benar menerimanya, selagi status mesej dalam Redis saya adalah [Menghantar], ini bermakna mesej itu tidak berjaya dihantar dengan betul. Kemudian mulakan tugas yang dijadualkan untuk memantau dan memulakan penghantaran pampasan.
Sudah tentu, kami juga boleh menambah nombor pampasan untuk tugasan yang dijadualkan Jika lebih daripada 3 kali dan masih tiada mesej ack diterima, maka teruskan tetapkan status mesej kepada [Gagal] dan biarkan orang menyemak sebabnya secara manual. ?
Dalam kes ini, penyelesaiannya lebih sempurna, memastikan 100% mesej tidak hilang (sudah tentu, ia tidak termasuk kegagalan cakera, jadi penyelesaian master-slave boleh digunakan).
Walau bagaimanapun, dengan penyelesaian ini, adalah mungkin untuk menghantar mesej yang sama beberapa kali. Besar kemungkinan MQ telah menerima mesej itu, tetapi terdapat kegagalan rangkaian semasa panggilan balik mesej ack, dan pengeluar tidak. menerimanya.
Maka kita mesti memerlukan pengguna untuk memastikan mati pucuk apabila mengambil!
Mari kita fahami apa itu mati pucuk? Dalam aplikasi yang diedarkan, mati pucuk adalah sangat penting, iaitu, jika perniagaan dikendalikan dalam keadaan yang sama, hasilnya akan sama tidak kira berapa kali ia dilakukan.
Kenapa ada senario seperti idempoten? Kerana dalam sistem yang besar, semuanya digunakan dalam cara yang diedarkan Contohnya, perniagaan pesanan dan perniagaan inventori boleh digunakan secara berasingan dan merupakan perkhidmatan yang berasingan. Apabila pengguna membuat pesanan, perkhidmatan pesanan dan perkhidmatan inventori akan dipanggil.
Disebabkan kerahan yang diedarkan, kemungkinan besar apabila memanggil perkhidmatan inventori, panggilan perkhidmatan pesanan gagal disebabkan oleh rangkaian dan sebab-sebab lain, bagaimanapun, sebenarnya, perkhidmatan inventori telah diproses, tetapi pengecualian berlaku semasa mengembalikannya hasil pemprosesan kepada perkhidmatan pesanan. Pada masa ini, sistem secara amnya akan membuat pelan pampasan, iaitu, perkhidmatan pesanan kemudiannya akan membuat panggilan ke perkhidmatan inventori, dan inventori akan dikurangkan sebanyak 1.
Ada masalah sebenarnya last call dah dikurangkan 1, tapi servis order belum dapat hasil pemprosesan. Kini ia dipanggil semula, dan ia perlu dikurangkan sebanyak 1. Ini tidak selaras dengan perniagaan, dan ia adalah potongan tambahan.
Konsep mati pucuk ialah tidak kira berapa kali perkhidmatan inventori dipanggil dalam keadaan yang sama, hasil pemprosesan akan tetap sama. Hanya dengan cara ini kebolehlaksanaan pelan pampasan dapat dipastikan.
Belajar daripada mekanisme penguncian optimistik pangkalan data, seperti:
Mengikut versi versi, iaitu, sebelum mendapatkan nombor versi dahulu produk semasa, dan kemudian kendalikan Bawa nombor versi ini. Mari kita selesaikan apabila kami mengendalikan inventori untuk kali pertama, kami mendapat versi 1, dan apabila kami memanggil perkhidmatan inventori, versi itu menjadi 2 tetapi terdapat masalah apabila kembali ke perkhidmatan pesanan panggilan ke perkhidmatan inventori Apabila perkhidmatan pesanan diluluskan sebagai Versi masih 1, dan apabila pernyataan SQL di atas dilaksanakan semula, ia tidak akan dilaksanakan kerana versi telah berubah kepada 2, keadaan di mana tidak berlaku; Ini memastikan bahawa tidak kira berapa kali ia dipanggil, ia hanya akan diproses sekali.
Prinsipnya ialah menggunakan kunci utama pangkalan data untuk mengalih keluar pendua Selepas perniagaan selesai, masukkan pengecam kunci utama
. ialah satu-satunya kunci utama jadual perniagaan, seperti ID produk
Kod cap jari adalah untuk membezakan kod bagi setiap operasi biasa Kod cap jari dijana untuk setiap operasi kaedah cap masa + nombor perniagaan boleh digunakan. .
Kelemahan: Kesesakan pangkalan data di bawah konkurensi tinggi
Ini bermakna inventori dikurangkan sebanyak 1, tetapi apakah yang perlu saya lakukan jika ia gagal apabila operasi redis melengkapkan tanda? Maksudnya, kita mesti memastikan pangkalan data jatuh dan redis sama ada berjaya atau gagal bersama
Atas ialah kandungan terperinci [Temu bual] Bagaimana untuk memastikan penghantaran mesej berjaya 100%? Bagaimana untuk memastikan keguguran mesej?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!