Architektura, Scheduling 100k wierszy per minute

0

Witam, nie mam pomysłu na rozwiązanie takiego problemu:

Mamy np jakąś usługe (ogłoszenie) które zostało wystawione o godzinie 15.00. Użytkownik jest wstanie ustalić potem godzine o której będzie ogłoszenie odświeżone tzn. wystawil ogloszenie we wtorek godz 14 i w srode o godz 15 (bo tak ustalił) będzie zmieniana po prostu inna zmienna. Teraz pytanie czy lepiej brać jakiś okres czasu np od 14.30 do 15.00 sciagac te ogloszenia w ktorych godzina znajduje sie w tym zakrecie czy ustawić scheduler co minute. Gdzie w tym zakresie może ich być około 100k. A jak postąpić jeśli byłoby ich milion?

2

Co to znaczy, ze "usługa jest odświeżania"? Jaki jest efekt "odswiezenia", co powinno się dziać jak usługa zostaje "odswiezona"?

3

Opisz wymaganie biznesowe i swoją propozycję rozwiązania. Najlepiej zdaniami max 7 wyrazów.

2

Kolego, ogarnij jakieś kropki i przecinki. Pierwszy akapit - kontekst, drugi - opis problemu i trzeci - propozycja rozwiązania.

0

Chodzi o date, np wystawiamy ogloszenie godz 17.30 kazdego dnia o tej godzinie ma sie odswiezac czyli ma sie zmieniac date na aktualna np ogloszenie 2 marca 17.30 nastepnego dnia scheduler o godzinie 17.30 odswieza to ogloszenie..
6.3
Rozwiazanie ustawic scheduler co minute zeby mi sciagal, czy co 30min i sprawdzac w odstepie czasu np jest 17 scheduler sie odali i sprawdza uslugi od 16.30 do 17.00 co bedzie bardziej wydajne np jesli w tym zakresie czasu znajdzie 100k ogloszen

1

Czekaj, czekaj, bo piszesz o jednym pytasz o drugie:

  • opis brzmi tak, jakbyś nie wiedział w jaki sposób obsłużyć jakieś harmonogramowanie zadania i pytał, co ile stosować jakiś np. polling by ustalić czy już teraz ma się coś wykonać
  • pytasz o co zrobić by nie spadła wydajność... pytanie czego?
  • gdzieś się przewija temat dużej liczby rekordów

Dobrze rozumiem, że Twoje rekordy tak naprawdę trzymają informację, kiedy ma się wykonać dane harmonogramowane zadanie, lub coś w ten deseń? Jeśli tak to może nie tyle ograniczanie dokładności pollingu czy coś, co założenie indeksu na kolumnie TIME

0

Rozumiem to w ten sposób, że użytkownik zapisuje taki "szablon" ogłoszenia z godziną, które będzie automatyczne wystawiane codziennie z tą godziną (ważne: nie o tej godzinie). Do tego pewnie liczba ponowień jest ograniczona (?). To może najprościej: przewalać wszystkie szablony co noc i powystawiać ogłoszenia. Jak masz ogłoszenie np. na wtorek godz. 14:00, to do tej godziny jest ono nieaktywne, tzn. użytkownik nie może się w nie wklikać, backend nie zwraca takiego zasobu. Przy takim podejściu milion szablonów nie powinno być żadnym problemem.

0
Xarenz napisał(a):

Chodzi o date, np wystawiamy ogloszenie godz 17.30 kazdego dnia o tej godzinie ma sie odswiezac czyli ma sie zmieniac date na aktualna np ogloszenie 2 marca 17.30 nastepnego dnia scheduler o godzinie 17.30 odswieza to ogloszenie..
6.3

A po co się ma zmieniać ta data? Piszesz o jakimś fragmencie rozwiązania jak je widzisz, ale bez podania jaki jest cel tego "odświeżenia".

Zakładam, że masz jakieś przypadki użycia typu:

  • "Dodaj ogłoszenie ważne X dni" (wówczas masz jakieś atrybuty typu: VALID_FROM = data_wystawienia_ogłoszenia, VALID_TO=data_wystawienia_ogłoszenia + X dni".
  • "Przedłuż ważność ogłoszenia o Y dni" (przedłużasz VALID_TO do data_biezaca + Y dni)
  • "Wyszukaj ogłoszenie" (i tu "ważność" ogłoszenia ma znaczenie, tzn. pokazujesz tylko ogłoszenia, dla których bieżąca data < VALID_TO).

Po co wtedy jakieś schedulery, skoro "bieżące" ogłoszenia wybierasz na podstawie "bieżącej daty"?

Chyba, że próbujesz rozwiązać jakiś inny problem? Jaki?

0

Autorowi chyba chodzi o coś takiego:

Poniedziałek:
Użytkownik wystawia ogłoszenie o godzinie 14:45 i ustala godzinę odświeżania na 15:00 każdego dnia.

(Mija doba ...)

Wtorek:

  • Przed 15:00 data wystawionego ogłoszenia to (Poniedziałek 14:45)
    (Wybija 15:00 - następuje "odświeżanie" ogłoszenia)
  • Po 15:00 data wystawionego ogłsozenia to (Wtorek 15:00)

(Mija doba...)

Środa:

  • Przed 15:00 data wystawionego ogłoszenia to (Wtorek 15:00)
    (Wybija 15:00 - następuje "odświeżanie" ogłoszenia)
  • Po 15:00 data wystawionego ogłsozenia to (Środa 15:00)

I tak dalej...

3

Jest taka biblioteka jak Quartz, która pozwala na tworzenie harmonogramów i zadań. Użytkownicy mogą za pomocą GUI zdefiniować, kiedy dane zadanie, implementacja Job, będzie uruchamiane. Twoim zadaniem jest pobrać taką konfigurację, przetłumaczyć na CronTrigger i wszytko ładnie składować.

Przy czym 100k definicji zadań to już dość dużo.

0

Rob co 5 minut z limitem czasu wykonania na 4m 30s.
Jak sie przestaniesz wyrabiac (zadania beda przyrastac w ciagu doby) to pomysl nad zrownolegleniem.
Czas t = 5 minut powinien byc duzo wiekszy od czasu podniesienia i zamkniecia zadania.

1

Na temat odpowiadaj w postach.

Zbior czytasz paczkami po k rekordow.
Jak przerobisz paczke i masz czas (wewnatrz tego okna 4m 30s) na przetworzenie kolejnej to bierzesz nastepna paczke.

1

@Xarenz:

użytkownik nie ma dostępu do ustalania czasu działania schedulera jedynie wybiera godzinie o ktorej ogloszenie ma zostac odswiezone to ja ustalam co ile ma działać żeby w tym czasie wykonać operacje na ogłoszeniu

Czyli jednak ma ten dostęp. W momencie, gdy użytkownik wybiera godzinę odświeżenia, to tworzysz zadanie i wrzucasz je do schedulera:

public class RefreshJob implements Job{
        public RefreshJob(){} // musi być w takiej formie niestety

       public void execute(JobExecutionContext context)
			throws JobExecutionException {

                // tak wyciągasz parametry
		JobDataMap data = context.getMergedJobDataMap();
		System.out.println("someProp = " + data.getString("someProp"));
	}

}

// gdzieś w kontrolerze albo serwisie obsługującym przyjmowanie danych od użytkownika

JobDetail job1 = newJob(RefreshJob.class)
    .withIdentity("refresh-job-UUID", "refresh-jobs")
    .usingJobData("someProp", "someValue") // tu dodajesz parametry, które wyciągasz z kontekstu
    .build();

Trigger trigger = newTrigger()
    .withIdentity("refresh-trigger-UUID", "refresh-triggers")
    .startNow()
    .withSchedule(dailyAtHourAndMinute(GODZINA_PODANA_PRZEZ_UŻYTKOWNIKA, MINUTA_PODANA_PRZEZ_UŻYTKOWNIKA)) // odpala się codziennie o podanej godzinie i minucie
    .build();

sched.scheduleJob(job, trigger); 

Gdzie sched jest skonfigurowanym schedulerem.

1

mhm, ok fajne a co jeśli kilku użytkowników poda tą samą godzine i minute? Chciałbym po tygodniu anulować ten trigger automatycznie, jest tak możliwość?

Tak jest. Na górze, w moim pierwszym poście, masz link do dokumentacji. Unscheduling jest możliwy. Jeżeli kilku użytkowników poda tą samą godzinę, to scheduler to spokojnie ogarnie za pomocą własnej puli wątków.

0

Quartz ogarnie milion zadań dziennie? Z tego, co wiem to Quartz nie działa w rozproszonym środowisku.

1

@Charles_Ray ogarnie milion, tylko trzeba wiedzieć jak to zrobić. Domyślna konfiguracja wymaga wtedy drobnych poprawek. Co do środowiska rozproszonego, to trzeba, niestety, postawić bazę danych i skonfigurować odpowiednio serwery. Chodzi o synchronizację czasu na maszynach, co nie jest trywialne, ale wykonalne.

http://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration/ConfigJDBCJobStoreClustering.html

Never run clustering on separate machines, unless their clocks are synchronized using some form of time-sync service (daemon) that runs very regularly (the clocks must be within a second of each other). See http://www.boulder.nist.gov/timefreq/service/its.htm if you are unfamiliar with how to do this.

0

Skoro tu w grę wchodzi tylko godzina jaka ma się wyświetlić użytkownikowi to może takie rozwiązanie udało by się jakoś zaimplementować? (z góry mówię, że nie siędze w webówce więc się nie orientuję). Jeżeli użytkownik wejdzie przed godziną, którą wybrał sobie użytkownik za "godzinę odświeżania" to wyświetla mu datę z dnia poprzedniego, jeśli już po tej godzinie, to z dnia dzisiejszego.

Czyli coś w stylu:

void showContent()
{
  var now = getDate();
  var refreshDate = getRefreshDateFromDatabase();

  if ( now.getTime() < refreshDate.getTime() )
  {
     setDate(now.getDate() - 1, now.getMounth(), now.getYear(), now.getTime());
  }
  else
  { 
     setDate(now.getDate(), now.getMounth(), now.getYear(), now.getTime());
  }
}

To taki pseudo kod w krokach można to rozpisać:

  1. pobierz aktualną datę
  2. pobierz datę odświeżania
  3. porównaj godzinę (teraz) oraz godzinę (odświeżania)
  4. jeśli mniejsza to ustaw dzień na poprzedni, w przeciwnym wypadku na aktualny.

I w zasadzie nic nie trzeba odświeżać w bazie, bo po co...

0

Stawiam ze te aukcje masz w jakiejs bazie SQL to moze nie kombinowac jak kon pod gore skoro z tego co piszesz potrzebujesz aktualizowac jedna zmienna i np co 1min robic update tych dat ktore w zakresie tej 1 min sie przedawnily zeby je podbilo?

Zapytanie mozesz odpalac quartzem, bazodanowo scheduler czy co tam wolisz

0

OP chce przetwarzać 100,000 rekordów biznesowych na minutę w bazie SQLowej. Nie wiadomo, jak to się tłumaczy na liczbę wierszy w tabelkach i indeksach. Cokolwiek się nie zaimplementuje, będzie trzeba tunować.
Tu nie ma prostych rozwiązań. Ja bym się skłaniał do „derived data”, tak jak to napisal @wyebani. Alternatywnie jakieś batchowanie - zakładam, że „odświeżenie” nie musi być wykonane dokładnie co do sekundy.

Quartz z milionem triggerów to jest ryzykowny pomysł. Quartz nie był zaprojektowany pod taki przypadek użycia. Domyślam się, że tabelki quartza wylądują w tej samej db, co przetwarzane dane. Wtedy każdy micro job dodatkowo będzie wymagał kilku zapytań quartzowych (z lockowaniem wierszy). To wybuchnie.

Można to usprawniać, ale gdy czytam, jak OP opisuje swój problem, to mam wątpliwości, czy powinien się zajmować takimi zagadnieniami.

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