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 PUBSUB
tidak berfungsi, karena saya tidak ingin semua pelanggan mengkonsumsi pekerjaan, saya hanya ingin satu pelanggan menerima pekerjaan. Pada awalnya, sepertinya bagiku BRPOPLPUSH
adalah desain yang cerdas.
Bisakah kita menggunakan BRPOPLPUSH?
Desain dasar dengan BRPOPLPUSH
Anda 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 LREM
dia. 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
PUBSUB
karena 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 digunakanPUBSUB
tanpa menghabiskan tugas dua kali adalah dengan hanya mendorong pemberitahuan bahwa pekerjaan telah tiba, yang kemudian dapat dilakukan konsumen tanpa pemblokiranRPOPLPUSH
. - 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.
sumber
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:
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:
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.
sumber
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.
sumber