Abbiamo un'app di servizio dati che funziona su grafici di oggetti. Inseriamo alcuni grafici complessi in un livello di memorizzazione nella cache (memoria) come un singolo elemento di dati, in modo da evitare il tempo necessario per recuperare ogni singolo elemento di dati nell'archiviazione su disco al fine di costruire l'intera gerarchia.
Ciò significa che ogni volta che uno qualsiasi degli elementi dei dati cambia, viene attivato un evento di ri-cache, ricaricando tutto nella gerarchia e memorizzando la versione più recente nella cache.
Recentemente abbiamo apportato modifiche al servizio per aumentare la concorrenza delle operazioni asincrone (principalmente I / O di rete) e osservato il comportamento di contesa se più richieste in ingresso hanno apportato aggiornamenti agli elementi essenzialmente nello stesso grafico a oggetti.
Ogni operazione di aggiornamento non è a conoscenza di altri aggiornamenti simultanei. A livello di persistenza dello spazio di archiviazione, l'infrastruttura dispone di data e ora sulle righe di dati; consentendoci di applicare tecniche di concorrenza ottimistiche, assicurando che nessuno stia scrivendo una versione obsoleta dello storage.
Una modifica in qualsiasi oggetto figlio fa sì che l'oggetto radice incrementi un numero di versione, quindi la riscrittura. Durante tale evento, possono verificarsi altri aggiornamenti simultanei per qualsiasi altro oggetto figlio (o anche lo stesso), il che rende difficile stabilire quale versione di root dell'oggetto si suppone abbia realmente (al momento dell'aggiornamento). Ciò che è peggio, e la preoccupazione principale qui, è che a causa della contesa simultanea dei thread per l'attenzione del processore, il tentativo di memorizzazione nella cache di una versione precedente può accadere dopo il tentativo di caching di una versione più recente.
In questo momento abbiamo ridotto al minimo questo comportamento verificando che la versione dell'oggetto root durante un evento di re-cache corrisponda ancora alla versione salvata durante la propria operazione di aggiornamento. Se il numero di versione non è lo stesso, significa che un altro aggiornamento simultaneo lo ha modificato ulteriormente e la re-cache non dovrebbe continuare - lascia che l'ultima operazione di aggiornamento esegua il re-cache.
Ovviamente riduce al minimo le probabilità, ma non elimina a titolo definitivo; può ancora essere possibile per l'oggetto radice conservare il suo numero di versione originale su re-fetch, e mentre recupera tutti gli oggetti figli, succede un altro aggiornamento e per colpo di fortuna (malata) riesce a completare e ri-cache prima di questo il tentativo di riprogrammazione in corso ha completato il suo ciclo.
Per complicare ulteriormente il problema, questo servizio dati viene distribuito come un cluster di server senza conoscenza reciproca dei fratelli.
Stava chiedendo se esiste un modo efficace per gestire gli aggiornamenti simultanei su più thread e server per garantire che la copia memorizzata nella cache sia effettivamente sempre la copia più recente?