Redis é uma solução viável para um cache local?

No meu cenário, Tenho um cliente Winforms que se liga ao WebApi2. Os dados são armazenados em um banco de dados do servidor SQL.

Para acelerar o desempenho, estou pesquisando se armazenar dados em cache local é 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. Os dados são todas classes POCO, algumas sendo muito mais complexas do que outras, e a maioria das classes sendo relacionadas umas com as outras.

Fiz uma pequena lista de quais os quadros que podem ser viáveis:

  1. MemoryCache
  2. MemCached
  3. CacheManager
  4. StackExchange.Redis
  5. 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 entre CustomerAddress 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?

Author: Ivan-Mark Debono, 2016-04-15

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} ".
E que o teu modelo é parecido com isto:
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.
Algo assim deve funcionar.
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) });
    }
}
 1
Author: thepirat000, 2016-04-17 06:53:07
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.

 1
Author: Orel Eraki, 2016-04-15 20:29:05