2015-08-06 28 views
5

Quindi ho del codice che tenta di trovare una risorsa su HDFS ... se non è lì calcolerà il contenuto di quel file, quindi lo scriverà. E la prossima volta che si accede al lettore può solo guardare il file. Questo serve a prevenire il costoso ricalcolo di certe funzioniCondivisione di una risorsa (file) tra diversi processi Python usando HDFS

Tuttavia ... Ho diversi processi in esecuzione contemporaneamente su macchine diverse nello stesso cluster. SOSPETTO che stanno provando ad accedere alla stessa risorsa e sto colpendo una condizione di competizione che porta un sacco di errori in cui non posso aprire un file o esiste un file ma non può essere letto.

Speriamo che questa linea temporale dimostrerà quello che ritengo il mio problema sia

  1. Processo A va per accedere risorsa X
  2. processo A ritrova esiste risorsa X e comincia a scrivere
  3. Processo B va per accedere risorsa X
  4. processo A finisce di scrivere risorsa X ... e così via

Ovviamente vorrei che Process B aspetti che il processo A sia fatto con Resource X e lo legga semplicemente quando A è pronto.

Mi vengono in mente alcuni semafori, ma non sono a conoscenza di come utilizzarli in più processi Python su processori separati che guardano la stessa posizione HDFS. Qualsiasi aiuto sarebbe molto apprezzato

AGGIORNAMENTO: Essere clear..process A e B processo finirà calcolo del medesimo uscita esatta (cioè lo stesso nome, con lo stesso contenuto, nella stessa posizione). Idealmente, B non dovrebbe dover calcolarlo. B aspetterebbe A per calcolarlo, quindi leggere l'output una volta che A è terminato. In sostanza, l'intero processo funziona come una "cache a lungo termine" utilizzando HDFS. Dove una determinata funzione avrà una firma di output. Qualsiasi processo che desideri l'output di una funzione determinerà innanzitutto la firma dell'output (questo è fondamentalmente un hash di alcuni parametri di funzione, input, ecc.). Quindi controllerà l'HDFS per vedere se è lì. Se non lo è ... scriverà calcolarlo e scriverlo sull'HDFS in modo che anche altri processi possano leggerlo.

+2

Puoi pubblicare il tuo codice? –

+0

Non è chiaro se i processi A e B riscriveranno la risorsa X, proveranno ad aggiungerli? Si deve scrivere dopo l'altro? –

+0

@SergeBallesta Ho aggiunto un aggiornamento che spero chiarisca la domanda – sedavidw

risposta

2

(Mettendo da parte che sembra che l'HDFS potrebbe non essere la soluzione giusta per il tuo caso d'uso, presumo che tu non possa passare a qualcos'altro. Se puoi, dai un'occhiata a Redis, o memcached.)

Sembra che questo è il tipo di cosa in cui si dovrebbe avere un singolo servizio responsabile per il calcolo/memorizzazione nella cache di questi risultati. In questo modo tutti i tuoi processi dovranno fare la richiesta che la risorsa venga creata se non lo è già. Se non è già calcolato, il servizio lo calcolerà; una volta che è stato calcolato (o se lo era già), un segnale che dice che la risorsa è disponibile, o anche solo la risorsa stessa, viene restituito al tuo processo.

Se per qualche motivo non è possibile farlo, è possibile provare a utilizzare HDFS per la sincronizzazione. Ad esempio, puoi provare a creare la risorsa con un valore sentinella all'interno del quale segnali che il processo A sta attualmente creando questo file. Nel frattempo il processo A potrebbe calcolare il valore e scriverlo su una risorsa temporanea; una volta terminato, potrebbe semplicemente spostare la risorsa temporanea sulla risorsa sentinella. È rozzo e hack, e dovresti cercare di evitarlo, ma è un'opzione.

Si dice di voler evitare ricalcoli costosi, ma se il processo B è in attesa del processo A per calcolare la risorsa, perché non è possibile elaborare B (e C e D) calcolandolo anche per sé/loro? Se ciò va bene per te, allora nel caso in cui una risorsa non esiste già, puoi semplicemente fare in modo che ogni processo inizi a calcolare e scrivere su un file temporaneo, quindi spostare il file nel percorso della risorsa. Speriamo che le mosse siano atomiche, quindi una di esse vincerà in modo pulito; non importa se sono tutti identici. Una volta lì, sarà disponibile in futuro. Ciò comporta la possibilità di più processi che inviano gli stessi dati al cluster HDFS allo stesso tempo, quindi non è il più efficiente, ma quanto è grave dipende dal tuo caso d'uso. Puoi ridurre l'inefficienza, ad esempio, controllando dopo il calcolo e prima di caricare su HDFS se qualcun altro ha creato la risorsa dall'ultima volta in cui hai guardato; se è così, non c'è nemmeno bisogno di creare la risorsa temporanea.

TLDR: È possibile farlo con un solo HDFS, ma sarebbe meglio avere un servizio che gestisce per voi, e probabilmente sarebbe ancora meglio non usare HDFS per questo (anche se si sarebbe ancora possibilmente vuoi che un servizio lo gestisca per te, anche se stai usando Redis o memcached, dipende, ancora una volta, dal tuo caso d'uso particolare).