Auteur : Iqbal Khan
Avec l'explosion des applications Web extrêmement transactionnelles, de la SOA, de l'informatique en grille et d'autres applications de serveur, le stockage des données ne peut pas suivre. La raison en est que le stockage de données ne peut pas continuer à ajouter plus de serveurs pour évoluer, contrairement aux architectures d'applications extrêmement évolutives.
Dans ces situations, le cache distribué en mémoire offre une excellente solution aux goulots d'étranglement du stockage de données. Il s'étend sur plusieurs serveurs (appelés cluster) pour regrouper leur mémoire et synchroniser tout le cache entre les serveurs. Et, il peut continuer à développer ce cluster de cache à l'infini, tout comme les serveurs d'applications. Cela réduit la pression sur le stockage des données afin qu'il ne soit plus un goulot d'étranglement pour l'évolutivité.
Il existe deux manières principales d'utiliser un cache distribué :
La mise en cache est une technique très puissante qui vous permet d'émettre des requêtes de base de données complexes impliquant des jointures et des requêtes imbriquées et de manipuler les données comme vous le souhaitez. Malgré que, Lire à travers / Ecriture présente divers avantages par rapport au cache, comme mentionné ci-dessous :
La lecture/écriture immédiate n'est pas destinée à être utilisée pour tous les accès aux données dans votre application. Il convient mieux aux situations où vous lisez des lignes individuelles de la base de données ou lisez des données qui peuvent directement être mappées à un élément de cache individuel. Il est également idéal pour les données de référence destinées à être conservées dans le cache pour des lectures fréquentes, même si ces données changent périodiquement.
Un gestionnaire de lecture directe est enregistré auprès du serveur de cache et permet au cache de lire directement les données de la base de données. le NCache Le serveur fournit une interface de gestionnaire de lecture que vous devez implémenter. Cela permet NCache pour appeler votre gestionnaire de lecture.
public class SqlReadThruProvider : IReadThruProvider
{
private SqlConnection _connection;
// Called upon startup to initialize connection
public void Init(IDictionary parameters, string cacheId)
{
_connection = new SqlConnection(parameters["connstring"]);
_connection.Open();
}
// Called at the end to close connection
public void Dispose()
{
_connection.Close();
}
// Responsible for loading object from external data source
public ProviderCacheItem LoadFromSource(string key)
{
string sql = "SELECT * FROM Customers WHERE ";
sql += "CustomerID = @ID";
SqlCommand cmd = new SqlCommand(sql, _connection);
cmd.Parameters.Add("@ID", System.Data.SqlDbType.VarChar);
// Let's extract actual customerID from "key"
int keyFormatLen = "Customers:CustomerID:".Length;
string custId = key.Substring(keyFormatLen,
key.Length - keyFormatLen);
cmd.Parameters["@ID"].Value = custId;
// fetch the row in the table
SqlDataReader reader = cmd.ExecuteReader();
Customers customer = new Customers();
// copy data from "reader" to "cust" object
FillCustomers(reader, customer);
ProviderCacheItem cacheItem = new ProviderCacheItem(customer);
// specify a SqlCacheDependency for this object
CacheDependency dep = new SqlCacheDependency(_connection.ToString(), cmd.ToString());
cacheItem.Dependency = dep;
return cacheItem;
}
Init()
effectue certaines tâches d'allocation de ressources telles que l'établissement de connexions à la source de données principale, tandis que Dispose()
est destiné à réinitialiser toutes ces allocations. LoadFromSource()
est ce que le cache appelle pour parcourir les objets.
Le gestionnaire d'écriture immédiate est appelé lorsque le cache doit écrire dans la base de données lors de la mise à jour du cache. Normalement, l'application publie une mise à jour du cache via l'ajout, l'insertion ou la suppression.
public class SqlWriteThruProvider : IWriteThruProvider
{
private SqlConnection _connection;
// Called upon startup to initialize connection
public void Init(IDictionary parameters, string cacheId)
{
_connection = new SqlConnection((string)parameters["connstring"]);
_connection.Open();
}
// Called at the end to close connection
public void Dispose()
{
_connection.Close();
}
public OperationResult WriteToDataSource(WriteOperation operation)
{
int rowsChanged = 0;
OperationResult result = new OperationResult(operation, OperationResult.Status.Failure);
ProviderCacheItem cacheItem = operation.ProviderItem;
Customers cust = cacheItem.GetValue<Customers>();
string[] customer = {cust.Id,cust.ContactName,cust.CompanyName,
cust.Address,cust.City, cust.Country,cust.PostalCode,
cust.Phone,cust.Fax};
SqlCommand cmd = _connection.CreateCommand();
cmd.CommandText = String.Format(CultureInfo.InvariantCulture,
"Update dbo.Customers " + "Set CustomerID='{0}'," +
"ContactName='{1}',CompanyName='{2}'," +
"Address='{3}',City='{4}'," +
"Country='{5}',PostalCode='{6}'," +
"Phone='{7}',Fax='{8}'" +
"Where CustomerID = '{0}'", customer);
rowsChanged = cmd.ExecuteNonQuery();
if (rowsChanged > 0)
{
result.OperationStatus = OperationResult.Status.Success;
return result;
}
return result;
}
}
Init()
effectue des tâches d'allocation de ressources telles que l'établissement de connexions à la source de données, tandis que Dispose()
est destiné à réinitialiser toutes ces allocations. Save est la méthode que le cache appelle pour les objets en écriture immédiate.
L'exemple de code suivant illustre l'utilisation des capacités de lecture/écriture du cache à partir d'une simple application Windows
using Alachisoft.NCache.Client;
...
internal class MainForm : System.Windows.Forms.Form
{
/// Fetches record from the cache, which internally accesses the
/// datasource using read-thru provider
private void OnClickFind(object sender, System.EventArgs e)
{
Customer customer;
Cache cache = NCache.Caches[CacheName];
string key = cboCustomerID.Text.Trim();
string providerName = cboReadThruProvider.Text;
customer = (Customer) cache.Get(key,
providerName,
DSReadOption.ReadThru);
...
}
/// Updates the record using the cache, which internally accesses
/// the datasource using write-thru provider
private void OnClickUpdate(object sender, System.EventArgs e)
{
Cache cache = NCache.Caches[CacheName];
Customer customer = new Customer();
...
string key = customer.CustomerID;
string providerName = cboWriteThruProvider.Text;
cache.Insert(key, new CacheItem(customer), DSWriteOption.WriteThru, providerName, null);
...
}
}