Як реалізувати чергу для повідомлень над Redis?


29

Чому Redis для черги?

Мені здається, що Redis може стати хорошим кандидатом для впровадження системи черги. До цього моменту ми використовували нашу базу даних MySQL з опитуванням або RabbitMQ. З RabbitMQ у нас виникло багато проблем - клієнтські бібліотеки дуже бідні і невдалі, і ми хотіли б не вкладати занадто багато годин для розробників на їх виправлення, кілька проблем з консоллю управління сервером тощо. І, до цього часу принаймні, ми не хапаємося на мілісекунди або серйозно підштовхуємо продуктивність, так що поки система має архітектуру, яка інтелектуально підтримує чергу, ми, мабуть, у хорошій формі.

Гаразд, так це тло. По суті, у мене дуже класична, проста модель черги - кілька виробників, які виробляють роботу, і кілька споживачів, що споживають роботу, і виробникам, і споживачам потрібно вміти інтелектуально масштабувати. Виявляється, наївний PUBSUBне працює, оскільки я не хочу, щоб усі підписники споживали роботу, я просто хочу, щоб один абонент отримав роботу. На перший прохід мені BRPOPLPUSHздається, що це розумна конструкція.

Чи можемо ми використовувати BRPOPLPUSH?

Основна конструкція, з BRPOPLPUSHякої ви маєте одну чергу роботи та чергу прогресу. Коли споживач отримує роботу, він атомарно штовхає товар у чергу виконання, а коли він закінчує роботу, він LREM- це. Це запобігає обробці роботи, якщо клієнти помирають, а моніторинг робить досить легким - наприклад, ми можемо сказати, чи є проблема, через яку споживачі потребують тривалого часу для виконання завдань, крім того, щоб повідомити про наявність великого обсягу завдань.

Це забезпечує

  • робота доставляється рівно одному споживачеві
  • Робота закінчується чергою прогресу, тож вона не може забитися, якщо споживач

Недоліки

  • Мені здається досить дивним, що найкращий дизайн, який я знайшов, насправді не використовує, PUBSUBоскільки, як видається, саме на цьому більшість публікацій у блогах щодо черги над Redis зосереджуються. Тож я відчуваю, що пропускаю щось очевидне. Єдиний спосіб, який я бачу використовувати PUBSUBбез використання завдань двічі, - це просто натиснути на повідомлення про те, що робота надійшла, і споживачі можуть потім не блокувати RPOPLPUSH.
  • Неможливо вимагати одночасно декілька робіт, що, здається, є проблемою ефективності. Це не величезна ситуація для нашої ситуації, але, очевидно, говорить, що ця операція не була розрахована на високу пропускну здатність або ситуацію
  • Коротше кажучи: я пропускаю щось дурне?

Також додаю тег node.js, тому що це мова, якою я маю справу переважно. Вузол може запропонувати деякі спрощення в застосуванні, враховуючи його однопоточний та неблокуючий характер, але крім того, я використовую бібліотеку вузла-переділу і рішення повинні або можуть бути чутливими до її сильних і слабких сторін.

Відповіді:


5

Якщо ви хочете використовувати Redis для черги повідомлень у Node.js, і ви не проти використовувати модуль для цього, тоді ви можете спробувати RSMQ - Redis Simple Queue Message for Node. На той момент це питання було недоступне, але сьогодні це життєздатний варіант.

Якщо ви хочете реально реалізувати чергу самостійно, як ви заявили у своєму запитанні, тоді ви можете прочитати джерело RSMQ, оскільки це лише 20 екранів коду, які роблять саме те, про що ви просите.

Побачити:


Я прийму це, якщо пізніше я не дізнаюся, що це дійсно несправно чи зламано.
дічлін

22

Поки я зіткнувся з деякими труднощами, я хотів би тут документувати.

Як ви поводитесь з логікою підключення?

Це важка проблема і особливо складна проблема в розробці та реалізації черги повідомлень. Повідомлення повинні бути в черзі де-небудь, коли споживачі перебувають у режимі офлайн, тому простий паб-підказник недостатньо сильний, і споживачі повинні знову підключитися в стані прослуховування. Блокуючі спливаючі вікна важко підтримувати, оскільки вони є неімпотенційним станом прослуховування . Прослуховування повинно бути самовпевненою операцією, але, маючи справу з відключенням щодо блокуючого попса, ви маєте задоволення дуже думати про те, чи відключення трапилось безпосередньо після успіху операції, або безпосередньо перед тим, як операція не відбулася. Це непереборне, але небажане.

Крім того, операція прослуховування повинна бути максимально простою. В ідеалі він повинен мати такі властивості:

  • Прослуховування є безсильним.
  • Споживач завжди слухає, а логіка дроселювання обробляється поза логічним кодом прослуховування. RabbitMQ інкапсулює це, дозволяючи споживачеві обмежити кількість нерозблокованих повідомлень, які він може мати.
    Зокрема, я пішов із поганим дизайном, коли повторний вхід до блокуючого попу залежав від успіху попередніх операцій, який був крихким і вимагав жорсткого роздуму.

Зараз я віддаю перевагу рішенню Redis PUBSUB + RPOPLPUSH. Це скасовує сповіщення про роботу від споживання праці, що дозволяє нам вибирати чисте прослуховування рішення. PUBSUB несе відповідальність лише за повідомлення про роботу. Атомна природа RPOPLPUSH відповідає за споживання та делегування роботи точно одному споживачеві. Спочатку це рішення здавалося непотрібним у порівнянні з блокуючим попсом, але тепер я бачу, що ускладнення зовсім не було зайвим; це було вирішення важкої проблеми.

Однак це рішення не зовсім банальне:

  • споживачі також повинні перевірити, чи є робота з підключення.
  • споживачі, можливо, захочуть зробити опитування на нову роботу в будь-якому випадку для надмірності. У разі успішного опитування слід надсилати попередження, оскільки це має відбуватися лише між споживанням на PUBSUB та опитуванням RPOPLPUSH. Тому багато успіхів опитування свідчать про порушену систему передплати.

Зауважте, що конструкція PUBSUB / RPOPLPUSH також має проблеми зі масштабуванням. Кожен споживач отримує легке повідомлення про кожне повідомлення, а це означає, що це непотрібне вузьке місце. Я підозрюю, що можна використовувати канали для розподілу роботи, але це, мабуть, складний дизайн, щоб добре випрацювати.


Не впевнений, що я стежу за проблемою із блокуванням споживачів. Мені здається, що якщо немає роботи по обробці споживачів, слід блокувати, поки не з’явиться якась робота, хоча я гадаю, якщо споживач також робить інші речі, які можуть бути іншою історією, але це не більше питання в програмі і не стільки для черги? IE не хотів, щоб блокування потоку в більшій програмі було більш елегантним рішенням, де потік зможе сповістити додаток, коли він отримав завдання з черги. Можливо, саме використання вузла створює ускладнення.
AaronM

9
Мені цікаво, як далеко ви зайшли з серпня минулого року. Чи змогли ви вирішити свої проблеми на ваше задоволення? Як ви їх вирішили?
AaronM

3
AAA: як і @AaronM, я хотів би почути, як ви прогресували.
bjornl

Домовились. Як це прогресувало? Мені подобається ідея зняти RabbitMQ зі стека і використовувати Redis, який там все одно є. Моє питання полягає в тому, як зареєструвати споживача за допомогою RSMQ (nb lib).
ra9r

@raiglstorfer не працював там два роки: P не соромтеся до досліджень та публікацій ...
djechlin

0

Тому найбільшою причиною вибору використовувати RabbitMQ над Redis є сценарії відмов та кластеризація.

Ця стаття справді пояснює це найкраще, тому я просто надам посилання:

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

Служебний сервіс Redis і останнім часом кластеризація Redis не в змозі обробити ряд дуже базових сценаріїв відмов, що зробило його поганим вибором для черги.

У RabbitMQ є свій набір питань, однак, за його словами, він надзвичайно міцний у виробництві і є гарною чергою на повідомлення.

Ось допис для кролика:

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

Якщо ви подивитеся на теорію CAP (послідовність, доступність та обробку розділів), ви можете вибрати лише 2 з 3. Ми використовуємо RMQ для CP (узгодженість та обробку розділів) з навантаженням нашого повідомлення, якщо ми недоступні, він не є ' t кінець світу. Щоб не втрачати повідомлення, ми використовуємо ігнорування для обробки розділів, щоб не втратити повідомлення. Дублікати можна обробляти, оскільки джерело управляє UUID.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.