Locking
Il problema della consistenza dei dati si presenta già quando, ad esempio, un applicazione web in esecuzione su di un singolo web server, accede alla cache di ASP.net. Lo stesso problema deve essere affrontato e risolto, a maggior ragione, quando la cache è distribuita come nel caso di Velocity, nel relativo cluster.
Velocity gestisce sia il lock pessimistico che quello ottimistico, il primo si ottiene con i metodi GetAndLock e PutAndUnlock di cui segue un esempio di codice:
Il metodo GetAndLock, richiede come parametro di output un oggetto tipo DataCacheLockHandle, è la “chiave” da utilizzare successivamente, quando occorrerà sbloccare l’oggetto nella cache:
Cosa succede se l’applicazione non riesce a sbloccare l’oggetto nella cache, ad esempio in seguito al verificarsi di un eccezione non gestita? In questo caso Velocity, allo scadere del timeout specificato, rimuoverà automaticamente il lock. Al contrario, se un oggetto bloccato raggiunge la sua scadenza (e rimozione dalla cache), questa viene posticipata fino alla rimozione del lock (ed eventualmente alla scadenza del timeout prima citato).
Attualmente Velocity non fornisce supporto per le transazioni, l’applicazione che la utilizza è responsabile della corretta gestione della sequenza di lock e di unlock degli oggetti nella cache e di eventuali deadlocks.
Il lock ottimistico, è supportato grazie alla gestione della versione dell’item conteso, tramite il tipo DataCacheItemVersion, che attualmente non espone alcun membro pubblico e di conseguenza nessuna informazione, fruibile dall’applicazione, circa la versione dell’item (vedi thread sul forum).
E’ sufficiente conservare una reference alla versione dell’item (ItemVersion), ottenuta con un overload del metodo Get, e successivamente ripassarla con il metodo Put che, in caso di una modifica da parte di un altro client, solleverà un eccezione.
Notifications
Velocity può esporre alle applicazioni client una serie di eventi relativi alla cache distribuita. Questo lascia immaginare diversi possibili benefici, ad esempio in scenari di sincronizzazione o comunque basati su notifiche.
E’ possibile gestire 3 diversi livelli di visibilità:
- Cluster-wide
- NamedCache (es. Catalog)
- Region (es. Televisions)
Le notifiche disponibili sono:
- CreateRegion
- ClearRegion
- RemoveRegion
- AddItem
- ReplaceItem
- RemoveItem
Le notifiche sono asincrone ed è necessario abilitarle preventivamente, in fase di creazione di una NamedCache, specificando il parametro –NotificationsEnabled, è inoltre necessario utilizzare un RoutingClient (descritto in questo post)
new-cache -CacheName DemoCache -TTL 1440 –NotificationsEnabled
Per motivi di performance, l’ordine di arrivo delle notifiche è garantito solo nel contesto di ogni singola region.
Prima di procedere alla sottoscrizione delle notifiche, occorre predisporre il codice di gestione delle stesse, che nel caso di un’applicazione Winform sarà simile a questo:
Si noti che la firma del metodo handler OnNotificationReceived offre tutte le informazioni relative alla notifica:
- il nome della namedCache (es. Catalog)
- il nome della Region (es. Televisions)
- la chiave dell’item nella cache
- la versione dell’item cui si riferisce la notifica
- il tipo di operazione effettuara (es. AddItem)
- il descrittore della notifica, da utilizzare per disabilitare la callback e la ricezione di tutte le notifiche successive.
Per iniziare a ricevere le notifiche, si procede con il seguente codice:
Sono evidenziati il delegate per la ricezione delle notifiche, creato in precedenza ed il metodo AddCacheLevelCallback, che ne abilita la ricezione.
E’ possibile specificare l’intervallo di polling delle notifiche in fase di creazione della DataCacheFactory (di default è 300 secondi).
Anche la LocalCache (descritta in questo post) può beneficiare delle notifiche, è possibile infatti scegliere una policy di sincronizzazione NotificationBased per ottenere aggiornare la LocalCache in seguito alla ricezione di una notifica di variazione di uno o più items. Diversamente si può optare per un aggiornamento basato su un TimeOut, specificato sempre in fase di creazione della DataCacheFactory.
Velocity utilizza una coda per mantenere in memoria le notifiche, è possibile che a causa di carichi elevati di uno o più server, oppure a causa di un guasto, alcuni client non ricevano le notifiche prima che queste vengano eliminate dalla coda. Tuttavia i client possono essere avvisati del verificarsi di questa condizione, tramite dei particolari tipi di notifiche detti FailureNotifications, la cui gestione è identica a quella illustrata nel codice di esempio.
Nota: Attualmente, con la CTP3 è stata segnalata una anomalia relativa all notifiche, successivamente dichiarata come bug (maggiori informazioni in questo thread).
posted @ giovedì 9 luglio 2009 00:00