Redis é uma solução viável para um cache local?
- MemoryCache
- MemCached
- CacheManager
- StackExchange.Redis
- Base De Dados Local
Usando {[[0]}, eu precisaria de implementar a minha própria solução, mas vai encaixar-se nas minhas necessidades iniciais.
No entanto, um problema comum que vejo é a actualização de classes relacionadas. Por exemplo, eu tenho uma relação entreCustomerAddress
e PostCode
. Se eu mudar algumas propriedades em um objeto de código postal, eu posso actualiza facilmente a sua 'cache' local. Mas como é possível atualizar/invalidar qualquer outra classe que use este código postal, neste caso CustomerAddress
?
algum dos frameworks acima tem métodos que ajudam neste tipo de situação, ou é totalmente dependente do desenvolvedor para lidar com tal invalidação de cache?
2 answers
O Quadro De Acaching.A biblioteca Redis oferece um mecanismo para relacionar as marcas com as chaves e as barras, para que possa invalidá-las numa única operação.
Presumo que sim.
- guardar os endereços dos clientes em Redis com chaves como " endereço: {AddressId} ".
- guardar os códigos postais em Redis com chaves como " Código Postal: {PostCodeId} ".
public class CustomerAddress
{
public int CustomerAddressId { get; set; }
public int CustomerId { get; set; }
public int PostCodeId { get; set; }
}
public class PostCode
{
public int PostCodeId { get; set; }
public string Code { get; set; }
}
A minha a sugestão é:
- marque os endereços dos clientes objectos em Redis com marcas como " Tag-Código Postal: {PostCodeId} ".
- utilize um padrão de reserva de cache para obter os endereços dos clientes e os códigos de Correio da cache/base de dados.
- invalida os objectos da 'cache' por marca quando um Código Postal for alterado.
public class DataAccess
{
private Context _cacheContext = new CachingFramework.Redis.Context("localhost:6379");
private string FormatPostCodeKey(int postCodeId)
{
return string.Format("PostCode:{0}", postCodeId);
}
private string FormatPostCodeTag(int postCodeId)
{
return string.Format("Tag-PostCode:{0}", postCodeId);
}
private string FormatAddressKey(int customerAddressId)
{
return string.Format("Address:{0}", customerAddressId);
}
public void InsertPostCode(PostCode postCode)
{
Sql.InsertPostCode(postCode);
}
public void UpdatePostCode(PostCode postCode)
{
Sql.UpdatePostCode(postCode);
//Invalidate cache: remove CustomerAddresses and PostCode related
_cacheContext.Cache.InvalidateKeysByTag(FormatPostCodeTag(postCode.PostCodeId));
}
public void DeletePostCode(int postCodeId)
{
Sql.DeletePostCode(postCodeId);
_cacheContext.Cache.InvalidateKeysByTag(FormatPostCodeTag(postCodeId));
}
public PostCode GetPostCode(int postCodeId)
{
// Get/Insert the postcode from/into Cache with key = PostCode{PostCodeId}.
// Mark the object with tag = Tag-PostCode:{PostCodeId}
return _cacheContext.Cache.FetchObject(
FormatPostCodeKey(postCodeId), // Redis Key to use
() => Sql.GetPostCode(postCodeId), // Delegate to get the value from database
new[] { FormatPostCodeTag(postCodeId) }); // Tags related
}
public void InsertCustomerAddress(CustomerAddress customerAddress)
{
Sql.InsertCustomerAddress(customerAddress);
}
public void UpdateCustomerAddress(CustomerAddress customerAddress)
{
var updated = Sql.UpdateCustomerAddress(customerAddress);
if (updated.PostCodeId != customerAddress.PostCodeId)
{
var addressKey = FormatAddressKey(customerAddress.CustomerAddressId);
_cacheContext.Cache.RenameTagForKey(addressKey, FormatPostCodeTag(customerAddress.PostCodeId), FormatPostCodeTag(updated.PostCodeId));
}
}
public void DeleteCustomerAddress(CustomerAddress customerAddress)
{
Sql.DeleteCustomerAddress(customerAddress.CustomerAddressId);
//Clean-up, remove the postcode tag from the CustomerAddress:
_cacheContext.Cache.RemoveTagsFromKey(FormatAddressKey(customerAddress.CustomerAddressId), new [] { FormatPostCodeTag(customerAddress.PostCodeId) });
}
public CustomerAddress GetCustomerAddress(int customerAddressId)
{
// Get/Insert the address from/into Cache with key = Address:{CustomerAddressId}.
// Mark the object with tag = Tag-PostCode:{PostCodeId}
return _cacheContext.Cache.FetchObject(
FormatAddressKey(customerAddressId),
() => Sql.GetCustomerAddress(customerAddressId),
a => new[] { FormatPostCodeTag(a.PostCodeId) });
}
}
Para acelerar o desempenho, estou pesquisando se armazenar dados em locais cache é uma solução viável. De preferência, o cache local deve ser armazenado em arquivos em vez de mantido na memória como RAM pode ser um problema
Toda a questão é evitar armazená-lo em arquivos, para evitar operações de disco que são lentas, assim Redis é memória baseada em RAM.
Algum dos quadros acima tem métodos que ajudam neste tipo de situações? de situação, ou é totalmente dependente de o programador a lidar tal invalidação de cache?
Você pode gravar o objecto inteiro como JSON em vez de aplicar a lógica e desmontar os objectos, que também serão lentos e propensos a erros ao aplicar alterações.