Zrównoleglanie pracy workera

0

Założmy, że mam stronę internetową. Po rejestracji każdy użytkownik ma dostać maila powitalnego. Chciałbym, by wysyłka tych maili była niezależna od backendu, dlatego utworzyłem aplikację, która cały czas odpytuje o bazę w poszukiwaniu nowych użytkowników i do nich wysyła maile.

Chciałbym to zrównoleglić. No i pojawia się problem wyścigu, by np. 2 wątki nie wysłały maila do tej samej osoby. Mógłbym wprowadzić coś w stylu blokady systemowej (np. poprzez Mutex) by na raz tylko 1 wątek pobierał dane z bazy, a potem je oznaczał jako "wzięte", ale średnio mi się podoba takie rozwiązanie.

Innym rozwiązaniem byłoby wprowadzenie czegoś takiego, by każdy wątek w selekcie miał dodatkowe WHERE id%{{LICZBA_WATKOW}} = {{INDEX_WATKU}} dzięki czemu przy np. 2 wątkach jeden z nich pobiera wiersze tylko parzyste, a drugi tylko nieparzyste.

Wiem że jest coś takiego jak kolejki, ale w obecnym rozwiązaniu chciałbym póki co ich uniknąć. Jakieś pomysły?

1

szukaj message queue in postgres. Alternatywnie osobna tabela na zadania do wysłania. Jak worker zaczyna pracować nad danym zadaniem to zmienia status, jak skończy to ustawia inny status.

1

Hmm a dlaczego nie uprościć tego i po rejestracji wysyłać event, że user sie zarejestrował i podejść do tego bardziej granularnie? Ja bym takiego batcha unikał ze względu na właśnie taki overhead, jaki opisujesz - musisz lecieć do bazy, robić jakiś polling, synchronizować wątki...

1

Czy to jest problem teoretyczny:

Założmy, że mam stronę internetową

Czy faktycznie istniejący:

ale w obecnym rozwiązaniu chciałbym póki co ich uniknąć.

Bo ja pominę w ogóle twoje rozważania i zapytam - czy faktycznie wysyłasz tyle tych maili powitalnych, że musisz to odpalać na 2 i więcej wątków? Mail nie musi przyjść natychmiast, jak user poczeka minutę to świat się chyba nie zawali.

0

Próbujesz trochę odkrywać koło na nowo i będziesz po drodze rozwiązywać masę problemów które już inni rozwiązali - np. co jeśli jakiś worker umrze w połowie wykonywania wysyłki maila? Co kiedy jakiś worker umrze i teraz pozostałe zamiast modulo 5, muszą brać numer wiersza modulo 4? Itp. itd.

Zakladając że faktycznie masz tyle userów że potrzebujesz to zrównoleglić, popatrz na gotowe rozwiązania. Możesz mieć np. jakiegoś task schedulera który ogarnia za ciebie to, że jeden task (tutaj task wysłania maila) weźmie tylko jeden worker. Kolejki których chcesz uniknąć, też by ci to zapewniły.

W jednym projekcie używałem https://github.com/kagkarlsson/db-scheduler i był całkiem spoko

No chyba że chcesz dla celów edukacyjnych, to droga wolna ale nie zaszkodzi spojrzeć jak już to zostało zrobione przez innych.

0

Zacznijmy od podstaw. Ile tych rejestracji na sekundę masz że czujesz potrzebę zrównoleglenia powiadomien na temat rejestracji? 1, 10, 100, 1000?

Pytanie 2 czy coś się stanie złego z punktu widzenia biznesowego, jeżeli użytkownik dostanie powiadomienie o rejestracji po 2 minutach zamiast po 5 sekundach? Pomijam problemy po stronie serwera pocztowego użytkownika.

0

i co ile pytasz bazę o te maile? Odpytywanie bazy czy coś się w niej pojawiło w pętli zamiast zareagować na to coś zanim wpadnie do bazy to najgłupsze co możesz zrobić

1 użytkowników online, w tym zalogowanych: 0, gości: 1