Come si può fare in modo che un cluster esegua un'attività una sola volta?


13

Se avessi un'attività che desideri eseguire una sola volta su un cluster di server, a intervalli regolari quale sarebbe il modo migliore per raggiungere questo obiettivo? La definizione di cluster in questo caso è 2 o più server identici con sessioni distribuite dietro un bilanciamento del carico.

Caso di utilizzo: un'attività costosa da eseguire che deve essere eseguita una sola volta per X ore. Questo lavoro, ad esempio, può scorrere su un mucchio di record e aggiornare il loro stato.

  • Lo scenario peggiore è che l'esecuzione del lavoro due volte invalida i dati.
  • Lo scenario migliore è che il lavoro utilizza risorse su tutti i server.

Riepilogo dei requisiti:

  1. Il processo deve comunque essere eseguito anche se uno dei nodi è inattivo.
  2. Il lavoro deve essere eseguito una sola volta per pianificazione.
  3. Se sono pianificati più lavori contemporaneamente o in momenti sovrapposti, il numero di lavori in esecuzione viene distribuito equamente tra i server.
  4. Le macchine devono avere la stessa base di codice ed essere sincronizzate tramite NTP.
  5. La configurazione può differire tra nodo e nodo, in base alle variabili di ambiente.
  6. Il lavoro deve iniziare in tempo o entro un determinato intervallo del tempo assegnato. (ad esempio 5 minuti)

Possibili soluzioni

  • Imposta un nodo come nodo principale, questo non funziona in quanto viola 1 sopra.
  • Inviare una richiesta di bilanciamento del carico per avviare il lavoro. Sfortunatamente questo ha l'effetto collaterale che se si hanno più lavori in esecuzione contemporaneamente possono essere tutti eseguiti dalla stessa macchina.

Questo dovrebbe essere eseguito in Java, in un contenitore servlet. Tuttavia non sta codificando i lavori che sto cercando.

Sicuramente questo è un problema risolto con la migliore soluzione conosciuta.


Domanda correlata. /programming/5949038/schedule-job-executes-twice-on-cluster

Questo non è un duplicato in quanto la soluzione non è sufficiente secondo quei 5 requisiti indicati sopra. La soluzione più votata soffre di un problema di gara e la seconda soluzione viola il requisito 3

Risposte:


16

Hai un database condiviso? Ho fatto questo usando un database come arbitro in passato.

Fondamentalmente, ogni "lavoro" è rappresentato come una riga nel database. Pianifichi un lavoro aggiungendo una riga al database con il tempo che vuoi che venga eseguito, quindi ogni server lo fa:

SELECT TOP 1 *
FROM jobs
WHERE state = 'NotRun'
ORDER BY run_time ASC

In questo modo, sceglieranno tutti il ​​lavoro che verrà pianificato per l'esecuzione successiva . Dormono tutti in modo da svegliarsi quando il lavoro dovrebbe essere eseguito. Quindi lo fanno tutti:

UPDATE jobs
SET state = 'Running'
WHERE job_id = :id
  AND state = 'NotRun'

Dov'è :idl'identificatore del lavoro che hai ottenuto nel passaggio sopra. Poiché l'aggiornamento è atomico, solo uno dei server aggiornerà effettivamente la riga, è possibile controllare il codice di stato "numero di righe aggiornamenti" del database per determinare se si è il server che ha effettivamente aggiornato la riga e quindi se si è il server che riesce a eseguire il lavoro.

Se non hai "vinto" e non stai eseguendo il lavoro, torna immediatamente al passaggio 1. Se hai "vinto", pianifica l'esecuzione del lavoro in un altro thread, quindi attendi un paio di secondi prima di tornare al passaggio 1. In questo modo, i server che non hanno ottenuto il lavoro questa volta hanno maggiori probabilità di raccogliere un lavoro che è programmato per essere eseguito immediatamente.


1
Quale livello di isloation stai usando qui? Leggi impegnato o serializzato?
Maverick Riz,

2

Diversi server di app dispongono di una funzione per "servizi singleton a livello di cluster".

Ad esempio Weblogic ha una funzione di servizio Singleton configurata tramite la console di amministrazione web.

Devi scrivere una classe che implementa weblogic.cluster.singleton.SingletonService e usarla per dichiarare il servizio nella console di amministrazione. Il cluster si occupa di creare un'istanza della classe e di avvisarti quando il servizio viene avviato o arrestato. L'interfaccia SingletonService ha un metodo activ () e un activate ().

Le chiamate Weblogic activano () quando avvia il servizio per la prima volta su uno dei nodi del cluster. Se il nodo selezionato scende, il server admin "sposta" il servizio su un altro server, chiamando activ () lì.

http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/clusters/ConfigureSingletonService.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.