Meccanismo di leasing di design di risorse condivise

3

Ho una risorsa condivisa in un database che viene utilizzato dai client C1 e C2. Prima che la risorsa venga letta da C1, C1 dovrebbe contrassegnare la risorsa come concessa in leasing in modo che C2 sappia che è occupato. C1 farà un po 'di lavoro e quando sarà finito aggiornerà il leasing per rendere la risorsa disponibile per C2. Sto usando un lease in modo che se il sistema host di Cx si blocca, un altro C sarà in grado di utilizzare la risorsa dopo il tempo T.

Il flusso è così:

Inizia transazione db

  1. C1 legge la risorsa e controlla il tempo di affitto per assicurarsi che current time >= leasetime + T

  2. C1 scrive il timestamp del tempo corrente nella colonna del lease

Termina transazione db

  1. C1 inizia a utilizzare la risorsa

  2. C2 legge la risorsa e controlla il tempo di affitto ma current time < leasetime + T quindi la risorsa è occupata

  3. C2 restituisce errore

  4. C1 è finito e scrive current time - T in lease

  5. C2 riprova (passaggio 1-3) e può ora noleggiare la risorsa

C1 e C2 non possono comunicare.

La mia ingenua implementazione è di taggare la risorsa con un timestamp dal sistema host per contrassegnarlo come un lease. Quando C2 tenta di leggere la risorsa, realizzerà che il timestamp è nel tempo T e che significa che la risorsa è occupata. C2 restituirà quindi un errore all'utente e chiederà loro di riprovare. Questa soluzione non funzionerà poiché dipende dall'ora di sistema dei sistemi host per C1 e C2 e quella volta potrebbe essere diversa.

Un pensiero che ho avuto è stato quello di utilizzare il tempo del database per fare i calcoli di quando la risorsa è in leasing o libero di usare. Essere dipendenti dal tempo sembra comunque una cattiva soluzione.

Come posso progettare questo per assicurarmi che Cn non utilizzerà la risorsa fino a quando C1 non è finito?

    
posta span 11.12.2017 - 11:54
fonte

1 risposta

1

C1 non schiaccia il caso

Inizia transazione db (assicurati di usare blocco esplicito !)

  1. C1 legge la risorsa e controlla che is_busy = false

  2. C1 scrive is_busy = true e leased_at con il timestamp corrente

Termina transazione db

  1. C1 inizia a utilizzare la risorsa

  2. C2 legge la risorsa e vede che is_busy è true

  3. C2 restituisce errore

  4. C1 è finito e scrive is_busy = false

  5. C2 riprova (passaggio 1-3) e può ora noleggiare la risorsa

C1 schiaccia il caso

Inizia transazione db

  1. C1 legge la risorsa e controlla che is_busy = false

  2. C1 scrive is_busy = true e leased_at con il timestamp corrente

Termina transazione db

  1. C1 schiaccia

  2. C2 legge la risorsa e vede che is_busy è true

  3. C2 restituisce errore

  4. Alcuni thread / processi / servizi / database separati (come pgAgent ) controlla se is_busy è stato bloccato per troppo tempo controllando il valore leased_at . La query potrebbe essere come update table set is_busy = false where is_busy = true and leased_at < now() - interval '15 minutes'

  5. C2 riprova (passaggio 1-3) e in 15 minuti può noleggiare la risorsa

risposta data 11.12.2017 - 13:50
fonte

Leggi altre domande sui tag