Gambaran
Setiap orang biasanya menggunakan beberapa middleware pesan (MQ), tetapi pemahaman mereka mungkin hanya tetap menggunakan API untuk mewujudkan produksi dan konsumsi pesan.
Untuk masalah MQ yang lebih mendalam, banyak orang mungkin belum memikirkannya.
Misalnya, saat Anda melompat untuk wawancara, jika pewawancara melihat resume Anda tertulis di dalamnya dan mahir dalam middleware pesan, maka kemungkinan besar akan memulai 4 gambar serial wawancara berikut untuk Anda!
- Mengapa menggunakan MQ?
- Apa keuntungan dan kerugian setelah menggunakan MQ?
- Bagaimana cara memastikan bahwa pesan MQ tidak hilang?
- Bagaimana cara memastikan ketersediaan tinggi MQ?
Artikel ini akan membahas masalah ini melalui beberapa adegan, dengan bahasa yang mudah dipahami dan beberapa gambar berwarna yang digambar dengan tangan.
Mengapa menggunakan MQ?
Saya yakin semua orang juga pernah mendengar kalimat seperti itu: Arsitektur yang baik tidak dirancang, tetapi berevolusi .
Kalimat ini juga berlaku untuk skenario di mana MQ diperkenalkan, harus ada alasan untuk menggunakan MQ, dan digunakan untuk menyelesaikan masalah praktis. Alih-alih melihat orang lain menggunakannya, saya juga menggunakannya untuk bersenang-senang.
Faktanya, ada banyak skenario untuk menggunakan MQ, tetapi ada 3 skenario inti:
asinkron
Kami mengilustrasikan melalui kasus aktual: misalkan sistem A menerima permintaan dan perlu menulis SQL secara lokal di perpustakaannya sendiri, dan kemudian perlu memanggil antarmuka dari tiga sistem BCD.
Misalkan dibutuhkan 3ms untuk menulis perpustakaan secara lokal, dan 300ms, 450ms, dan 200ms untuk memanggil tiga sistem BCD.
Maka total penundaan permintaan akhir adalah 3 + 300 + 450 + 200 = 953ms, yang mendekati 1s, yang mungkin terlalu lambat bagi pengguna.
Saat ini, keseluruhan sistem terlihat seperti ini:
Tapi begitu MQ digunakan, sistem A hanya perlu mengirim 3 pesan ke 3 antrian pesan di MQ, dan kemudian kembali ke pengguna.
Dengan asumsi bahwa dibutuhkan 20ms untuk mengirim pesan ke MQ, pengguna merasa bahwa antarmuka hanya membutuhkan waktu 20 + 3 = 23ms, dan pengguna hampir tidak memiliki persepsi, yang keren!
Saat ini, keseluruhan struktur sistem kira-kira seperti ini:
Dapat dilihat bahwa melalui fungsi asynchronous dari MQ, kinerja antarmuka dapat sangat ditingkatkan.
Decoupling
Misalkan sistem A perlu mendorong data yang dikirimkan oleh pengguna ke sistem B dan C pada saat yang sama ketika operasi tertentu terjadi.
Saat ini, orang yang bertanggung jawab atas sistem A berpikir: Tidak apa-apa. Sistem B dan C memberi saya antarmuka Http atau antarmuka RPC. Bukankah akan berakhir jika saya mendorong data? Teman yang bertanggung jawab atas sistem A sangat senang.
Seperti yang ditunjukkan di bawah ini:
Semuanya terlihat bagus, tetapi dengan iterasi bisnis yang cepat, sistem D juga menginginkan data ini saat ini. Dalam hal ini, pengembang sistem A mengubahnya dan menambahkan D saat mengirim data ke BC.
Namun, semakin saya mengetahuinya kemudian, masalahnya datang. . .
Seluruh sistem tampaknya tidak hanya mengirim data ini ke BCD, tetapi juga data kedua dan ketiga untuk dikirim ke BCD. Kadang-kadang bahkan sistem E, F, dll. Ditambahkan, dan mereka juga menginginkan data ini.
Dan terkadang sistem B tiba-tiba tidak membutuhkan data ini, sistem A harus diubah, dan pengembang sistem A mati rasa.
Skenario yang lebih rumit adalah ketika data dikirim ke sistem lain melalui antarmuka, beberapa situasi abnormal seperti coba lagi dan batas waktu terkadang dipertimbangkan, dan rambut benar-benar berwarna abu-abu. . .
Lihatlah gambar di bawah ini untuk mengalami pemandangan tak berdaya ini:
Pada saat ini, inilah saatnya MQ kami untuk debut!
Dalam hal ini, sebaiknya menggunakan MQ untuk memisahkan, karena teman yang bertanggung jawab atas sistem A hanya perlu membuang pesan ke MQ, dan sistem lain dapat berlangganan pesan sesuai permintaan.
Bahkan jika sistem tertentu tidak membutuhkan data ini, tidak perlu sistem A untuk mengubah kodenya.
Perhatikan gambar di bawah ini dengan tambahan decoupling MQ, sangat menyegarkan!
Pencukuran puncak dan pengisian lembah
Misalnya, dalam sistem pesanan kami, data akan ditulis ke database saat pesanan dilakukan. Namun, database hanya dapat mendukung sekitar 1.000 penulisan serentak per detik, dan tidak peduli seberapa tinggi konkurensi tersebut, mudah terjadi error.
Selama periode puncak rendah, ada lebih dari 100 konkurensi, tetapi selama periode puncak, konkurensi tiba-tiba melonjak hingga lebih dari 5000, dan basis data pasti mati saat ini.
Seperti yang ditunjukkan di bawah ini, untuk merasakan keputusasaan database yang terbunuh:
Tetapi setelah menggunakan MQ, situasinya berubah!
Pesan disimpan oleh MQ, dan kemudian sistem dapat mengkonsumsinya sesuai dengan kapasitas konsumsinya sendiri, misalnya 1000 data per detik, sehingga perlahan-lahan ditulis ke database, sehingga database tidak akan mati:
Seluruh proses ditunjukkan pada gambar berikut:
Adapun mengapa disebut peak cutting dan valley filling? Coba lihat gambar ini:
Jika MQ tidak digunakan, ada " puncak ", dan setelah periode puncak adalah konkurensi rendah" Lembah ".
Namun, setelah menggunakan MQ, tingkat konsumsi pesan dibatasi hingga 1000, tetapi dengan cara ini, data yang dihasilkan selama periode puncak pasti akan macet di MQ, dan puncak akan "dipotong".
Namun, karena adanya simpanan pesan, laju konsumsi pesan akan tetap pada 1000QPS untuk periode waktu setelah periode puncak, sampai simpanan pesan dikonsumsi, yang disebut "mengisi lembah".
Melalui analisis di atas, Anda dapat mengetahui mengapa Anda ingin menggunakan MQ dan apa saja keuntungan menggunakan MQ. Mengetahui alasannya, saya memahami mengapa sistem saya menggunakan MQ.
Dengan cara ini, ketika seseorang bertanya mengapa Anda ingin menggunakan MQ di masa mendatang, tidak akan ada jawaban yang canggung seperti "Pemimpin tim kami ingin menggunakan MQ, jadi kami akan menggunakannya".
Apa keuntungan dan kerugian setelah menggunakan MQ?
Melihat masalah ini, saya terjebak, gunakan saja! Keunggulannya telah disebutkan di atas, tetapi apa kerugiannya. Sepertinya tidak ada kekurangan.
Jika Anda berpikir seperti ini, Anda salah besar, dalam proses mendesain sebuah sistem, selain mengetahui dengan jelas mengapa Anda ingin menggunakan benda ini, Anda juga harus memikirkan kerugian dari menggunakannya. Hanya dengan cara ini kita dapat memiliki hati yang jernih dan waspada terhadapnya.
Selanjutnya akan kita bahas, apa saja kerugian menggunakan MQ?
Ketersediaan sistem berkurang
Coba pikirkan, semuanya. Skenario decoupling di atas. Awalnya, sobat Sistem A ingin mengirimkan data kunci dari sistem ke sistem BC. Sekarang mereka tiba-tiba menambahkan MQ. Sekarang sistem BC menerima data melalui MQ.
Tapi pernahkah Anda mempertimbangkan sebuah pertanyaan, bagaimana jika MQ turun? Hal ini menimbulkan pertanyaan, setelah menambahkan MQ, apakah ketersediaan sistem berkurang?
Karena ada faktor resiko tambahan: MQ bisa hang. Selama MQ hang dan data hilang, sistem akan berjalan salah.
Peningkatan kompleksitas sistem
Awalnya, sistem saya dapat dilakukan dengan satu panggilan melalui antarmuka, tetapi setelah menambahkan MQ, Anda perlu mempertimbangkan masalah konsumsi pesan yang berulang, kehilangan pesan, dan bahkan urutan pesan.
Untuk mengatasi masalah ini, banyak mekanisme yang rumit perlu diperkenalkan, jadi apakah kompleksitas sistem meningkat?
Masalah konsistensi data
Awalnya, sistem memanggil antarmuka sistem BC. Jika sistem BC membuat kesalahan, pengecualian akan dilemparkan dan dikembalikan ke sistem A untuk memberi tahu sistem A, sehingga operasi rollback dapat dilakukan.
Tetapi setelah menggunakan MQ, sistem A selesai setelah mengirim pesan dan menganggapnya berhasil. Dan kebetulan sistem C gagal saat menulis database, tetapi A mengira C telah berhasil? Akibatnya, datanya tidak konsisten.
Setelah menganalisis keuntungan dan kerugian dari memperkenalkan MQ, saya memahami bahwa menggunakan MQ memiliki banyak keuntungan, tetapi Anda akan menemukan bahwa kerugian yang ditimbulkannya akan mengharuskan Anda untuk melakukan berbagai desain sistem tambahan untuk menebusnya.
Pada akhirnya, Anda mungkin menemukan bahwa keseluruhan sistem beberapa kali lebih kompleks, jadi ketika mendesain sistem, Anda harus membuat trade-off berdasarkan pertimbangan ini. Dalam banyak kasus, Anda akan menemukan bahwa yang harus Anda gunakan masih yang Anda butuhkan. . .
Bagaimana cara memastikan bahwa pesan MQ tidak hilang?
Setelah menggunakan MQ, Anda juga harus memperhatikan masalah kehilangan pesan. Di sini kami memilih RabbitMQ untuk diilustrasikan.
Produser kehilangan data
Ketika produsen RabbitMQ mengirim data ke rabbitmq, data mungkin hilang selama transmisi jaringan, Saat ini RabbitMQ tidak dapat menerima pesan, dan pesan hilang.
RabbitMQ menyediakan dua cara untuk mengatasi masalah ini:
Mode transaksi:
Sebelum produser mengirim pesan, mulailah transaksi melalui `channel.txSelect`, lalu kirim pesan
Jika pesan tidak berhasil diterima oleh RabbitMQ, produser akan menerima pengecualian, dan transaksi dapat diputar kembali `channel.txRollback` dan kemudian dikirim ulang. Jika RabbitMQ menerima pesan ini, RabbitMQ bisa melakukan transaksi `channel.txCommit`.
Tetapi dengan cara ini, throughput dan kinerja produsen akan banyak berkurang, dan umumnya tidak dilakukan sekarang.
Cara lain adalah melalui mekanisme konfirmasi:
Mode konfirmasi ini disetel di produser, yaitu, id unik diberikan setiap kali pesan ditulis, dan kemudian RabbitMQ akan mengembalikan ack setelah menerimanya, memberi tahu produser bahwa pesannya ok.
Jika rabbitmq tidak memproses pesan tersebut, ia akan memanggil kembali antarmuka nack, dan kemudian produser dapat mengirimnya kembali.
Mekanisme transaksi dan mekanisme perusahaan Perbedaan terbesar Karena mekanisme transaksinya sinkron, ia akan memblokir di sana setelah melakukan transaksi
Tetapi mekanisme konfirmasi adalah asynchronous.Setelah mengirim pesan, Anda dapat mengirim pesan berikutnya, dan kemudian setelah pesan diterima, Rabbitmq akan secara asynchronous menelepon Anda kembali dan sebuah antarmuka untuk memberitahu Anda bahwa pesan tersebut telah diterima.
Jadi umumnya Produsen menggunakan mekanisme konfirmasi untuk menghindari kehilangan data .
Rabbitmq kehilangan data
Cluster RabbitMQ juga akan kehilangan pesan. Masalah ini juga disebutkan dalam tutorial dokumentasi resmi, yaitu, setelah pesan dikirim ke RabbitMQ, tidak ada landing disk secara default. Jika RabbitMQ mati, pesan akan hilang saat ini. .
Jadi untuk mengatasi masalah ini, RabbitMQ menyediakan file Kegigihan Mekanismenya, pesan akan disimpan ke disk setelah ditulis
Dengan cara ini, meskipun sedang down, data yang disimpan sebelumnya akan otomatis dikembalikan setelah pemulihan, mekanisme ini dapat memastikan bahwa pesan tidak akan hilang.
Ada dua langkah untuk menyiapkan persistensi:
- Yang pertama adalah mengaturnya menjadi persisten ketika antrian dibuat, sehingga dapat memastikan bahwa rabbitmq mempertahankan metadata antrian, tetapi tidak mempertahankan data dalam antrian
- Yang kedua adalah mengatur deliveryMode pesan ke 2 saat mengirim pesan, yaitu mengatur pesan menjadi persisten, saat ini rabbitmq akan menyimpan pesan ke disk.
Tapi dengan cara ini, beberapa orang mungkin berkata: Bagaimana jika pesan dikirim ke RabbitMQ dan hang sebelum dapat disimpan ke disk dan datanya hilang?
Untuk masalah ini, sebenarnya dijamin dengan mekanisme konfirmasi di atas bahwa pesan ack dikirim ke produsen setelah pesan disimpan ke disk.
Jika situasi ekstrim benar-benar ditemui, produsen dapat melihatnya. Saat ini, produsen dapat mengirim pesan ke node RabbitMQ lainnya dengan mencoba kembali
Konsumen kehilangan data
Situasi ketika konsumen RabbitMQ kehilangan data adalah seperti ini: Saat mengkonsumsi pesan, langsung terima pesannya, dan hasilnya adalah proses hang. Pada saat ini, RabbitMQ akan berpikir bahwa Anda telah berhasil menggunakan data, dan data ini hilang.
Untuk masalah ini, pertama-tama kita harus menjelaskan mekanisme pesan konsumsi RabbitMQ: ketika konsumen menerima pesan, ia akan mengirim ack ke RabbitMQ untuk memberi tahu RabbitMQ bahwa pesan telah dikonsumsi, jadi RabbitMQ akan menghapus pesan tersebut.
Namun, secara default, operasi pengiriman ack secara otomatis dikirimkan, yang berarti konsumen akan secara otomatis mengembalikan ack ke RabbitMQ segera setelah pesan diterima, sehingga akan terjadi masalah hilangnya pesan.
Jadi solusi untuk masalah ini adalah dengan mematikan pengiriman ack otomatis dari konsumen RabbitMQ, lalu secara manual mengirimkan ack setelah konsumen memproses pesan tersebut.
Dengan cara ini, bahkan jika situasi di atas terjadi, RabbitMQ tidak akan menghapus pesan ini, dan akan mengeluarkan kembali pesan ini setelah program Anda dimulai ulang.
Bagaimana cara memastikan ketersediaan tinggi MQ?
Setelah menggunakan MQ, kami pasti berharap MQ memiliki fitur ketersediaan tinggi, karena tidak mungkin menerima situasi di mana mesin mati dan tidak dapat mengirim dan menerima pesan.
Karya ini juga didasarkan pada MQ klasik seperti RabbitMQ untuk menggambarkan:
RabbitMQ lebih representatif, karena didasarkan pada master-slave ketersediaan tinggi, kami akan menggunakan dia sebagai contoh untuk menjelaskan bagaimana mencapai tipe pertama MQ ketersediaan tinggi.
Rabbitmq memiliki tiga mode: mode berdiri sendiri, mode cluster normal, mode cluster cermin
Mode berdiri sendiri
Mode berdiri sendiri berada pada level demo, yang berarti hanya satu mesin yang memiliki program RabbitMQ yang diterapkan.
Akan ada satu titik masalah, dan waktu henti akan berakhir, tidak ada ketersediaan tinggi. Biasanya Anda memulai permainan secara lokal, dan tidak ada yang memproduksinya dalam mode berdiri sendiri.
Mode cluster normal
Mode ini berarti memulai banyak instance rabbitmq di banyak mesin. Mirip dengan mode master-slave.
Tetapi antrian yang dibuat hanya akan ditempatkan pada satu instance rabbtimq master, dan instance lainnya akan menyinkronkan metadata RabbitMQ yang menerima pesan tersebut.
Saat menggunakan pesan, jika instans RabbitMQ yang Anda sambungkan bukan instans yang menyimpan data Antrean, RabbitMQ akan menarik data dari instans yang menyimpan data Antrean saat ini, dan kemudian mengembalikannya ke klien.
Secara umum, metode ini agak rumit, dan tidak benar-benar didistribusikan. Setiap kali konsumen terhubung ke sebuah instance, data ditarik. Jika terhubung ke sebuah instance yang tidak menyimpan data antrian, ini akan menyebabkan overhead kinerja tambahan. Jika Anda menarik dari instance tempat Antrean ditempatkan, ini akan menyebabkan kemacetan kinerja satu-instance.
Jika instance antrian turun, instance lain tidak akan dapat menarik data, cluster ini tidak akan dapat menggunakan pesan, dan tidak akan benar-benar tersedia.
Jadi masalah ini lebih memalukan, Tidak ada yang namanya ketersediaan tinggi. Solusi ini terutama untuk meningkatkan throughput, yaitu, biarkan beberapa node dalam kluster melayani operasi baca dan tulis dari antrian tertentu.
Mode cluster cermin
Mode cluster yang dicerminkan adalah mode ketersediaan tinggi rabbitmq yang sebenarnya. Perbedaan dari mode cluster normal adalah bahwa antrian yang dibuat akan ada di beberapa contoh terlepas dari metadata atau pesan dalam antrian.
Setiap kali pesan ditulis ke antrian, pesan secara otomatis dikirim ke antrian beberapa contoh untuk sinkronisasi pesan.
Dengan cara ini, mesin apa pun mati dan kejadian lain dapat digunakan untuk menyediakan layanan, sehingga ketersediaan tinggi yang nyata tercapai.
Tetapi ada juga kerugiannya:
- Overhead kinerja terlalu tinggi, dan pesan perlu disinkronkan ke semua mesin, yang akan menyebabkan tekanan dan konsumsi bandwidth jaringan yang berat
- Skalabilitas rendah: Tidak dapat menyelesaikan masalah jumlah data yang sangat besar dalam antrian, yang mengakibatkan antrian tidak dapat diperluas secara linier.
- Bahkan jika mesin ditambahkan, mesin itu akan berisi semua data antrian, dan data antrian tidak disimpan secara terdistribusi.
Pendekatan umum untuk ketersediaan tinggi RabbitMQ adalah dengan mengaktifkan mode kluster cermin, sehingga setidaknya ketersediaan tinggi tercapai. Saat satu node tidak aktif, node lain dapat terus menyediakan layanan.
Untuk menyimpulkan
Melalui artikel ini, beberapa masalah umum dengan MQ dianalisis:
- Mengapa menggunakan MQ?
- Apa keuntungan dan kerugian menggunakan MQ
- Bagaimana cara memastikan bahwa pesan tersebut tidak hilang?
- Bagaimana cara memastikan ketersediaan tinggi MQ?
Namun, masalah ini hanya sebagian dari masalah yang perlu diperhatikan saat menggunakan MQ. Faktanya, ada masalah lain yang lebih kompleks yang perlu kita selesaikan.
- "TWICE" "Share" 190617 "TWICE" menduduki peringkat keempat dalam "Japan Oricon Semi-Annual Chart Top 50"
- Pidato bahasa Inggris Yuan Longping yang berusia 89 tahun meledakkan Internet: dia adalah kebanggaan China yang sebenarnya
- GIGABYTE secara resmi merilis solid state drive PCIe 4.0: menggunakan tembaga murni untuk pembuangan panas
- Dia mengendarai 44 negara dalam 7 tahun dan dirampok dengan pisau tiga kali: jika dia tidak bisa mati, dia akan terus berangkat
- Menulis pada usia 4 tahun, menerbitkan buku pada usia 13 tahun dan menjadi presiden pada usia 14 tahun, berbagi panggung dengan Hawking pada usia 14 tahun, anak ini sangat mengesankan