Questo è un problema classico che sono sicuro sia stato risolto molte volte da molte persone diverse. Non ho alcun corso di formazione formale (non ho studiato informatica o altri argomenti accademici simili) e quindi non sono sicuro del modo migliore per risolvere il problema che sto per descrivere.
Se immaginiamo che il diagramma sottostante sia un esempio di dilemma dei banchieri (due utenti Foo e Bar hanno accesso a un singolo conto bancario: Baz). Qual è il comportamento previsto quando si segue uno dei percorsi indicati?
Note: I'm assuming we're using a mutex (or some other form of synchronisation) on the Baz variable.
Esempio 1: Baz inizialmente detiene il valore 10. Se Foo scrive un nuovo valore (che è il risultato della rimozione di 5 dal valore corrente) prima di Bar; quindi la barra finirà col prendere 10 dal nuovo valore 5, lasciando un saldo negativo (ad esempio il valore finale sarà -5). Significa che sono stati presi più soldi di quelli disponibili.
Esempio 2: Baz inizialmente detiene il valore 10. Se Bar scrive un nuovo valore (che è il risultato della rimozione di 10 dal valore corrente) prima di Foo; quindi Foo finirà col prendere 5 dal nuovo valore 0, lasciando un saldo negativo (ad esempio il valore finale sarà -5). Significa che sono stati presi più soldi di quelli disponibili.
Entrambe le azioni ( Foo (-5)
e Bar (-10)
) vengono attivate contemporaneamente. Quindi, come possiamo garantire che Foo o Bar siano avvisati del fatto che la loro transazione non può essere completata (in quanto non ci sono fondi sufficienti per il successo)?
Sembra che una possibile soluzione sia garantire che il chiamante esegua un metodo che utilizza internamente un mutex per bloccare prima il valore; poi una volta che il valore è bloccato possiamo leggere il valore; e quindi controllare se l'azione è valida. Se la condizione passa, aggiorniamo il valore e rilasciamo il blocco sul valore. Significa che il prossimo chiamante sarà in grado di bloccare il valore e di eseguire gli stessi passi.
Ma come funzionerebbe questo approccio con un sistema distribuito? Puoi suggerire di utilizzare un archivio dati globale, ma dovrebbe essere tale da garantire la coerenza (ad esempio, un servizio come AWS "Dynamo DB offre" coerenza finale "e quindi non funzionerebbe per un istituto bancario); ma la consistenza garantita è generalmente considerata molto lenta (a seconda del numero di nodi distribuiti che presumo).
Quindi, come possiamo tentare di risolvere questo problema di progettazione?