Przetwarzanie bazy danych z użyciem wielu consumerów

0

Hej, od jakiegoś czasu zastawiam się jak najlepiej przetworzyć bazę danych w przypadku wielu instancji aplikacji.

Np. mam główną tabelę w której są dane które chciałbym przetworzyć w jakiś tam sposób.

I teraz problem jest taki że wiele replik może chcieć przetworzyć te same rekordy (a tego chciałbym uniknąć), pomyślałem że może warto by było dodać dodatkową kolumnę do tej tabeli i przypisać tam jakąś konkretną instancję (na zasadzie round robin czy coś) no i teraz mógłbym robić coś w stylu

SELECT * FROM MY_TABLE WHERE STATUS='NEW' and INSTANCE_ID='InstanceId1'

pobieranie by było wywoływanie shedulerem.

Powyższe rozwiązanie ma też zapobiec sytuacji kiedy instancja z jakiegoś powodu będzie off ( inny serwis będzie też zmieniał INSTANCE_ID dla takich sytuacji i będzie wybierał tylko te które są obecnie działające)

Co o tym sądzicie? Znacie lepsze sposoby?

0

A czy rekordy są przetwarzane pojedynczo czy w paczkach. Czy ma znaczenie kolejność przetwarzania?

0
Tomek Pycia napisał(a):

A czy rekordy są przetwarzane pojedynczo czy w paczkach. Czy ma znaczenie kolejność przetwarzania?

kolejność przetwarzania nie ma znaczenia.

rekordy są przetwarzane pojedynczo

0

Atomowo rezerwujesz sobie paczkę rekordów (np. SELECT FOR UPDATE), a potem na spokojnie je przetwarzasz.

0

No to prosty zabieg jest taki, że każda instancja bierze tylko "swoje" rekordy. Jak masz 5 instancji, to każda bierze co piąty rekord (można na wyliczyć na podstawie id). Jak masz niezdefiniowaną ilość instancji to jedyna opcja to blokowanie tabeli przy odczycie i nadawanie statusu (in porogress) rekordom, tak żeby inne instancje tego go nie przetwarzały. Możesz tu dużo czasu stracić na tym, ze instancje będą czekać na siebie.

4

wrzuciłbym wszystkie idki do przetworzenia na kolejkę, i niech sobie konsumenci pobierają z niej idki każdy w swoim tempie i potem pobierają dane z bazy po idku.
Rozproszenie pracy prawie w ogóle by nie dotknęło wydajnościowo bazy, zero dodatkowych blokad, praca byłaby rozkładana elastycznie, każdy konsument by pracował na maksa, i łatwo byłoby przejść na przetwarzanie partami niż pojedynczych rekordów za jednym razem.

0
Tomek Pycia napisał(a):

No to prosty zabieg jest taki, że każda instancja bierze tylko "swoje" rekordy. Jak masz 5 instancji, to każda bierze co piąty rekord (można na wyliczyć na podstawie id). Jak masz niezdefiniowaną ilość instancji to jedyna opcja to blokowanie tabeli przy odczycie i nadawanie statusu (in porogress) rekordom, tak żeby inne instancje tego go nie przetwarzały. Możesz tu dużo czasu stracić na tym, ze instancje będą czekać na siebie.

no tak, ale jak dodam kolumnę w której będzie przypisane ID instancji (zakładam istnienie serwisu który będzie to uzupełniał dość szybko, i również kasował w razie potrzeby) to czy wtedy nie wystarczy
zykłego selecta ?

SELECT * FROM MY_TABLE WHERE STATUS='NEW' and INSTANCE_ID='Instance1'

przykład tabeli:

STATUS INSTANCE_ID MESSAGE
NEW Instance1 xml1
NEW Instance2 xml2
NEW Instance3 xml3
0
neves napisał(a):

wrzuciłbym wszystkie idki do przetworzenia na kolejkę, i niech sobie konsumenci pobierają z niej idki każdy w swoim tempie i potem pobierają dane z bazy po idku.
Rozproszenie pracy prawie w ogóle by nie dotknęło wydajnościowo bazy, zero dodatkowych blokad, praca byłaby rozkładana elastycznie, każdy konsument by pracował na maksa, i łatwo byłoby przejść na przetwarzanie partami niż pojedynczych rekordów za jednym razem.

czyli co, po prostu postawić instancję np RabbitMQ i wskazać tabelę którą chcę przetwarzać ?

A gdybym chciał uniknąć dodatkowego komponenta to jak mógłbym to inaczej wykonać?

0

Niektóre bazy mają mechanizm kolejkowania zaimplementowany w sobie. Poszukaj czy twoja baza
tego nie wspiera.

2

Zamiast kombinować z implementowaniem kolejki na bazie sqlowej, użyj kolejki :) Bo teraz to wyprodukujesz jakąś abominacje nie do utrzymania, z masą bugów i to wszytko tylko po to, zeby nie dodać gotowego komponentu który działa out of the box.

0
Shalom napisał(a):

Zamiast kombinować z implementowaniem kolejki na bazie sqlowej, użyj kolejki :) Bo teraz to wyprodukujesz jakąś abominacje nie do utrzymania, z masą bugów i to wszytko tylko po to, zeby nie dodać gotowego komponentu który działa out of the box.

no to chyba tak będę musiał zrobić.
a podpowiecie jeszcze co dalej z tym procesowaniem się robi w przypadku gdy jedna instancja padnie podczas procesowania?
Kolejki sobie radzą z takimi sytuacjami? Czy kwestia konfiguracja zwrotki?

3

@procekStm32 hm to zależy od kolejki. Robiłem kiedyś coś podobnego na AWS SQS i tam możesz wyciągnąć element z kolejki (tak że nikt inny go nie wyciągnie przez pewien czas) i musisz explicite zrobić na nim delete (kiedy np. skończyłeś procesowanie). Jeśli tego delete nie zrobisz, bo np. się wywaliłeś, to po upłynięciu visibility period element znowu pojawi się w kolejce. W RabbitMQ to się nazywa manual acknowledgment

3
procekStm32 napisał(a):

a podpowiecie jeszcze co dalej z tym procesowaniem się robi w przypadku gdy jedna instancja padnie podczas procesowania?
Kolejki sobie radzą z takimi sytuacjami? Czy kwestia konfiguracja zwrotki?

w zależności jak sobie skonfigurujesz kolejkę, RabbitMQ umożliwia potwierdzanie wiadomości, jak nie potwierdzisz odebranej wiadomości w określonym przedziale czasu, instancja zostanie uznana za martwą i wiadomość wróci z powrotem do kolejki.

2

Jak masz możliwość dodania nowego komponentu (który też trzeba potem utrzymywać), to bierz pan Rabbita jak koledzy wyżej piszą. W sumie o wiele łatwiej to potem utrzymać niż własny rozproszony scheduler.

0
Charles_Ray napisał(a):

Jak masz możliwość dodania nowego komponentu (który też trzeba potem utrzymywać), to bierz pan Rabbita jak koledzy wyżej piszą. W sumie o wiele łatwiej to potem utrzymać niż własny rozproszony scheduler.

Hej, dzięki wszystkim za odpowiedzi chyba znalazłem coś co spełnia moje oczekiwania
https://camel.apache.org/components/latest/jpa-component.html#_consuming_from_the_endpoint

wydaje mi się że działa to na takiej samej zasadzie którą przedstawialiście.

Więc dzięki za naprowadzenie.

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