Bagaimana cara menerapkan antrian pesan di atas Redis?

29

Mengapa Redis harus antri?

Saya mendapat kesan bahwa Redis dapat menjadi kandidat yang baik untuk menerapkan sistem antrian. Hingga saat ini kami telah menggunakan database MySQL kami dengan polling, atau RabbitMQ. Dengan RabbitMQ kami memiliki banyak masalah - perpustakaan klien sangat buruk dan bermasalah dan kami ingin tidak menginvestasikan terlalu banyak waktu pengembang untuk memperbaikinya, beberapa masalah dengan konsol manajemen server, dll. Dan, untuk saat ini setidaknya, kita tidak memahami selama milidetik atau secara serius mendorong kinerja, jadi selama suatu sistem memiliki arsitektur yang mendukung antrian dengan cerdas, kita mungkin dalam kondisi yang baik.

Oke, jadi itu latar belakangnya. Pada dasarnya saya memiliki model antrian yang sangat klasik dan sederhana - beberapa produsen yang menghasilkan pekerjaan dan beberapa konsumen yang mengkonsumsi pekerjaan, dan baik produsen maupun konsumen harus dapat meningkatkan skala secara cerdas. Ternyata naif PUBSUBtidak berfungsi, karena saya tidak ingin semua pelanggan mengkonsumsi pekerjaan, saya hanya ingin satu pelanggan menerima pekerjaan. Pada awalnya, sepertinya bagiku BRPOPLPUSHadalah desain yang cerdas.

Bisakah kita menggunakan BRPOPLPUSH?

Desain dasar dengan BRPOPLPUSHAnda memiliki satu antrian kerja dan antrian kemajuan. Ketika seorang konsumen menerima pekerjaan itu secara atomis mendorong item ke dalam antrian kemajuan, dan ketika itu menyelesaikan pekerjaan itu LREMdia. Ini mencegah blackholing pekerjaan jika klien mati dan membuat pemantauan cukup mudah - misalnya kita dapat mengetahui apakah ada masalah yang menyebabkan konsumen membutuhkan waktu lama untuk melakukan tugas, di samping memberi tahu jika ada banyak tugas.

Itu memastikan

  • pekerjaan dikirim ke tepat satu konsumen
  • pekerjaan berakhir dalam antrian kemajuan, sehingga tidak dapat blackhole jika konsumen

Kekurangannya

  • Tampaknya agak aneh bagi saya bahwa desain terbaik yang saya temukan tidak benar-benar digunakan PUBSUBkarena ini tampaknya menjadi tujuan kebanyakan posting blog tentang antrian atas fokus Redis. Jadi saya merasa seperti kehilangan sesuatu yang jelas. Satu-satunya cara saya melihat untuk digunakan PUBSUBtanpa menghabiskan tugas dua kali adalah dengan hanya mendorong pemberitahuan bahwa pekerjaan telah tiba, yang kemudian dapat dilakukan konsumen tanpa pemblokiran RPOPLPUSH.
  • Tidak mungkin untuk meminta lebih dari satu item pekerjaan pada satu waktu, yang tampaknya menjadi masalah kinerja. Bukan yang besar untuk situasi kita, tetapi lebih jelas mengatakan operasi ini tidak dirancang untuk throughput tinggi atau situasi ini
  • Singkatnya: apakah saya kehilangan sesuatu yang bodoh?

Juga menambahkan tag node.js, karena itulah bahasa yang paling saya hadapi. Node dapat menawarkan beberapa penyederhanaan dalam implementasi, mengingat sifatnya single-threaded dan nonblocking, tetapi lebih lanjut saya menggunakan perpustakaan node-redis dan solusi harus atau bisa peka terhadap kekuatan dan kelemahannya juga.

Djechlin
sumber

Jawaban:

5

Jika Anda ingin menggunakan Redis untuk antrian pesan di Node.js dan Anda tidak keberatan menggunakan modul untuk itu maka Anda dapat mencoba RSMQ - Antrian Pesan Sederhana Redis untuk Node. Itu tidak tersedia pada saat pertanyaan ini diajukan tetapi hari ini itu adalah pilihan yang layak.

Jika Anda ingin benar-benar mengimplementasikan antrian sendiri seperti yang Anda nyatakan dalam pertanyaan Anda, maka Anda mungkin ingin membaca sumber RSMQ karena hanya 20 layar kode yang melakukan persis seperti yang Anda minta.

Lihat:

rsp
sumber
Saya akan menerima ini kecuali saya nanti tahu itu benar-benar cacat atau rusak atau sesuatu.
djechlin
22

Saya telah mengalami beberapa kesulitan sejauh ini yang ingin saya dokumentasikan di sini.

Bagaimana Anda menangani koneksi ulang logika?

Ini adalah masalah yang sulit dan masalah yang sangat sulit dalam merancang dan mengimplementasikan antrian pesan. Pesan harus dapat mengantri di suatu tempat ketika konsumen sedang luring, sehingga pub-sub sederhana tidak cukup kuat, dan konsumen perlu menyambung kembali dalam keadaan mendengarkan. Memblokir pop adalah kondisi yang sulit untuk dipertahankan, karena mereka adalah kondisi mendengarkan yang tidak idempoten . Mendengarkan harus merupakan operasi idempoten, namun ketika berhadapan dengan disconnect sehubungan dengan pop yang menghalangi, Anda dengan senang hati berpikir tentang apakah disconnect terjadi tepat setelah operasi berhasil atau tepat sebelum operasi gagal. Ini tidak dapat diatasi, tetapi tidak diinginkan.

Selanjutnya, operasi mendengarkan harus sesederhana mungkin. Idealnya seharusnya memiliki sifat-sifat ini:

  • Mendengarkan adalah idempoten.
  • Konsumen selalu mendengarkan, dan pelambatan logika diproses di luar kode logika mendengarkan. RabbitMQ merangkum hal ini dengan membiarkan konsumen mengikat jumlah pesan kosong yang bisa dimilikinya.
    Secara khusus saya menggunakan desain yang buruk di mana memasukkan kembali pop pemblokiran bergantung pada keberhasilan operasi sebelumnya, yang rapuh dan membutuhkan pemikiran keras.

Saya sekarang menyukai solusi Redis PUBSUB + RPOPLPUSH. Ini memisahkan pemberitahuan pekerjaan dari konsumsi pekerjaan, yang memungkinkan kami memfaktorkan solusi mendengarkan yang bersih. PUBSUB hanya bertanggung jawab untuk pemberitahuan pekerjaan. Sifat atom RPOPLPUSH bertanggung jawab untuk konsumsi, dan mendelegasikan pekerjaan ke satu konsumen. Pada awalnya solusi ini tampaknya tidak perlu rumit dibandingkan dengan pop yang menghalangi, tetapi sekarang saya melihat bahwa kerumitan itu sama sekali tidak perlu; itu memecahkan masalah yang sulit.

Namun solusi ini tidak sepele:

  • konsumen juga harus memeriksa pekerjaan pada koneksi kembali.
  • konsumen mungkin ingin melakukan polling untuk pekerjaan baru, untuk redundansi. Jika jajak pendapat benar-benar berhasil, peringatan harus dikeluarkan, karena ini seharusnya hanya terjadi antara konsumsi pada PUBSUB dan jajak pendapat pada RPOPLPUSH. Karenanya banyak keberhasilan jajak pendapat menunjukkan sistem berlangganan yang rusak.

Perhatikan bahwa desain PUBSUB / RPOPLPUSH juga memiliki masalah penskalaan. Setiap konsumen menerima pemberitahuan ringan dari setiap pesan, yang berarti ini memiliki hambatan yang tidak perlu. Saya menduga mungkin untuk menggunakan saluran untuk bekerja, tetapi ini mungkin desain yang rumit untuk bekerja dengan baik.

Djechlin
sumber
Tidak yakin saya mengikuti masalah dengan memblokir konsumen. Sepertinya saya bahwa jika tidak ada pekerjaan untuk memproses, konsumen harus memblokir sampai ada beberapa, meskipun saya kira jika konsumen juga melakukan hal-hal lain yang mungkin cerita yang berbeda, tetapi bukankah itu lebih merupakan masalah dalam aplikasi dan tidak begitu banyak untuk antrian? IE tidak akan memblokir utas dalam aplikasi yang lebih besar menjadi solusi yang lebih elegan, di mana utas kemudian dapat memberi tahu aplikasi ketika telah mengambil pekerjaan dari antrian. Mungkin hanya penggunaan simpul yang menciptakan komplikasi.
AaronM
9
Saya ingin tahu seberapa jauh Anda telah datang sejak Agustus lalu. Apakah Anda mampu menyelesaikan masalah Anda untuk kepuasan Anda? Bagaimana Anda mengatasinya?
AaronM
3
AAA: sama seperti @AaronM, saya ingin mendengar perkembangan Anda.
bjornl
Sepakat. Bagaimana ini berkembang? Saya suka ide menghapus RabbitMQ dari tumpukan dan menggunakan Redis yang ada di sana. Masalah saya adalah bagaimana cara mendaftarkan konsumen menggunakan RSMQ (lib node).
ra9r
@raiglstorfer tidak bekerja di sana selama dua tahun: P jangan ragu untuk meneliti dan memposting ...
djechlin
0

Jadi alasan terbesar untuk memilih menggunakan RabbitMQ daripada Redis adalah skenario kegagalan, dan pengelompokan.

Artikel ini benar-benar menjelaskan yang terbaik, jadi saya hanya akan memberikan tautannya:

https://aphyr.com/posts/283-jepsen-redis

Redis sentinel dan baru-baru ini redis clustering tidak dapat menangani sejumlah skenario kegagalan yang sangat mendasar yang menjadikannya pilihan yang buruk untuk antrian.

RabbitMQ memiliki masalah sendiri, namun dikatakan sangat solid dalam produksi dan merupakan antrian pesan yang bagus.

Inilah pos untuk kelinci:

https://aphyr.com/posts/315-jepsen-rabbitmq

Ketika Anda melihat teorema CAP (konsistensi, ketersediaan, dan penanganan partisi), Anda hanya dapat memilih 2 dari 3. Kami memanfaatkan RMQ untuk CP (konsistensi dan penanganan partisi) dengan beban pesan kami, jika kami tidak tersedia, bukan t akhir dunia. Agar pesan tidak hilang, kami menggunakan abaikan untuk penanganan partisi agar pesan tidak hilang. Duplikat dapat ditangani karena sumber mengelola UUID.

ra9r
sumber