2009-08-04 34 views
13

Ho un codice che voglio consentire solo l'accesso a un thread. So come farlo usando i blocchi oi metodi synchronized, ma funzionerà in un ambiente cluster?Condivisione di un blocco sincronizzato Java in un cluster o utilizzando un blocco globale?

L'ambiente di destinazione è WebSphere 6.0, con 2 nodi nel cluster.

Ho la sensazione che synchronized non funzionerà, poiché ogni istanza dell'applicazione su ciascun nodo avrà la sua JVM, giusto?

Quello che sto cercando di fare qui è eseguire alcuni aggiornamenti ai record del database quando il sistema viene avviato. Cercherà tutti i record del database che sono più vecchi della versione del codice ed eseguirà attività specifiche per aggiornarli. Voglio solo un nodo per eseguire questi aggiornamenti, dal momento che voglio essere sicuro che ogni elemento di lavoro viene aggiornato solo una volta, e le prestazioni di questi aggiornamenti non sono una grande preoccupazione, dal momento che accade solo all'avvio dell'applicazione, e fa davvero solo qualcosa quando il codice è stato modificato dall'ultima volta che è stato avviato.

Il database è DB2v9 e accedo direttamente tramite JNDI (nessun livello ORM).

È stato suggerito che un blocco globale potrebbe essere la strada da percorrere qui, ma non sono sicuro di come farlo.

Qualcuno ha qualche indicazione in questa arena?

Grazie!

+0

Penso che dovresti essere più specifico nella tua domanda. Quale azione, esattamente, stai cercando di coordinare? –

+0

@Software Monkey- Sure, mi dispiace per quello. Ho appena aggiunto un paragrafo che spiega il mio intento. Per favore fatemi sapere se non è ancora chiaro. – pkaeding

+0

Quindi quello che vuoi veramente, allora, è un blocco globale. Non conosco la websphere quindi non posso aiutare qui, ma chiedere aiuto nella creazione di una serratura probabilmente suonerà più campane con quelli che lo fanno :) – bdonlan

risposta

5

È corretto che la sincronizzazione tra processi non funzioni utilizzando i costrutti di sincronizzazione Java. Fortunatamente, il tuo problema in realtà non è quello della sincronizzazione del codice, ma piuttosto della sincronizzazione delle interazioni con il database.

Il modo corretto per risolvere questo problema è con blocchi a livello di database. Presumibilmente hai una tabella che contiene una versione dello schema db, quindi dovresti assicurarti di bloccare quella tabella per la durata del processo di avvio/aggiornamento.

Le precise chiamate sql/db coinvolte sarebbero probabilmente più chiare se si specifica il tipo di database (DB2?) E il metodo di accesso (raw sql, jpa, ecc.).

Aggiornamento (8/4/2009 2:39 PM): Suggerisco l'istruzione LOCK TABLE su una tabella contenente la versione # dello schema. Questo serializzerà l'accesso a quella tabella impedendo a due istanze di eseguire contemporaneamente il codice di aggiornamento.

+0

Il database è DB2v9 e sto accedendo direttamente tramite JNDI (nessun livello ORM). Ho appena modificato la domanda per riflettere questo. Grazie! – pkaeding

0

Impossibile semplicemente bloccare la tabella (o l'intero db) per gli aggiornamenti, quindi quando il primo nodo ha ottenuto il blocco, tutti gli altri nodi non sarebbero in grado di scrivere. I nodi successivi sarebbero in attesa e, quando verrà rilasciato il blocco, il codice verrà aggiornato in modo che non sia necessario alcun aggiornamento del record.

7

Sì, si è corretto in quanto i blocchi sincronizzati non funzioneranno in un cluster. Il motivo è, come hai affermato, che ogni nodo ha la sua JVM.

Ci sono modi, tuttavia, per far funzionare i blocchi sincronizzati in un cluster poiché funzionerebbero in un ambiente a nodo singolo. Il modo più semplice è utilizzare un prodotto come Terracotta, che gestirà il coordinamento dei thread tra diverse JVM in modo da poter utilizzare normali controlli di concorrenza all'interno del cluster. Ci sono molti articoli che spiegano come funziona, come Introduction to OpenTerracotta.

Ci sono altre soluzioni, ovviamente. Dipende principalmente da ciò che vuoi veramente ottenere qui. Non utilizzerei i blocchi del database per la sincronizzazione se è necessario ridimensionare, in quanto DB non lo fa. Ma ti esorto davvero a trovare una soluzione pronta, perché fare casino con la sincronizzazione dei cluster è un business disordinato :)

+0

OK, dopo aver esaminato i chiarimenti aggiuntivi nella domanda, sembra che in questo caso l'utilizzo di Terracotta potrebbe essere come sparare a mosche con un cannone molto grande :) – Kaitsu

3

Dato che stai parlando di 2 macchine, non hai nemmeno la memoria condivisa quindi non c'è nulla da sincronizzare .

Facciamo qualcosa di simile con il nostro database. Questo risultato è ottenuto aggiungendo il controllo delle versioni nella tabella. Questo è quello che dovresti fare,

  1. Aggiungere una colonna per la versione record/riga.
  2. Passare attraverso la logica per verificare se è necessario aggiornare il record.
  3. Quando si aggiorna il record, assicurarsi che la versione del record in DB sia la stessa di quella in uso.
  4. Aumentare la versione ogni volta che si scrive nel database.

Si dovrebbe avere un solo server che aggiorna il database se si seguono queste regole.

+2

Non si chiama "blocco ottimistico"? – LuGo

4

Anche per questo è possibile utilizzare una griglia di dati in memoria come http://www.hazelcast.com/. Questa è una struttura dati distribuita che supporta il blocco.

Problemi correlati