Base solution for your next web application
Open Closed

Distributed caching using Redis #7618


User avatar
0
sumitshah created

Hi,

We have 2 load balanced web server and we need to implement distributed caching for some of the frequently used SQL tables. The documentation is not clear, https://aspnetboilerplate.com/Pages/Documents/v1.5.2/Caching

https://docs.aspnetzero.com/documents/aspnet-core-mvc/latest/Infrastructure-Core-Mvc-Caching

We have uncommented the code for Redis in the pre initialize method of the webcoremodule.cs.

We have also setup the redis server as a windows service on a windows machine using the below link: https://github.com/MicrosoftArchive/redis/releases

how can we proceed further. How and where(in which project) can we actually write the code to set the cache with the data from SQL table.


9 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    You can use the ICacheManager to cache your query results in the application service layer (please cache dto instead of entity)

    https://aspnetboilerplate.com/Pages/Documents/Caching#icachemanager

  • User Avatar
    0
    sumitshah created

    Thank you,

    We have setup the caching of a particular table as mentioned and the same is getting cached as desired using the cacheManager.

    While unit testing we came across a scenario. Post uncommenting the use of Redis as cacheManager, everything is getting saved on the redis server(setup on a separate machine as a windows service). THis includes the token validity key as well. THis key is being validated every time a api request is made from the ValidateToken method(JwtSecurityTokenHandler.cs file)

    If for some reason the Redis service stops or the machine altogether reboots/shuts down, the entire site stops and the user is redirected to the login page.

    THis is not the case if we have multiple web servers(load balanced) and we are using in-memory caching instead of Redis. We tried this by login into our website(the request is being served by server 1), browsing the website for a while. Then stopping the IIS of server 1 and trying to browse the site further, the request is automatically served by server2 without user getting throw out to the login page.

    How can this be achieved when using distributed caching?

    Also, is there a possibility that the system uses pre-defined in-memory caching for caching the token and abp tables, while for caching particular SQL tables we use distributed caching.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    When you enable the line "UseRedis", this code is executed https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/src/Abp.RedisCache/Runtime/Caching/Redis/RedisCacheConfigurationExtensions.cs#L30

    It basically replaces the implementation of ICacheManager with AbpRedisCacheManager.

    So, you can leave UseRedis line uncommented and inject AbpRedisCacheManager class where you want to use Redis cache. Rest of the usages of ICacheManager will use In-Memory cache in that case.

  • User Avatar
    0
    sumitshah created

    You mean to say leave UseRedis commented right? Cause if we uncomment the code, all the caching is done on redis.

    If we inject the AbpRedisCacheManager class, how can we define the connection string of the server. It always takes localhost:6379 as the connection string. My web server and the redis server would be placed on different physical servers. Below is the code snippet of the impelementation:

    If I run it locally with redis server setup on my machine, everything is working as desired. But what if I want to point to a different redis server.

  • User Avatar
    0
    maliming created
    Support Team

    You can override it with the delegate parameter of UseRedis.

    Example:

    Configuration.Caching.UseRedis(options =>
    {
        options.ConnectionString = _appConfiguration["RedisCache:ConnectionString"];
        options.DatabaseId = _appConfiguration.GetValue<int>("RedisCache:DatabaseId");
    });
    
  • User Avatar
    0
    sumitshah created

    But if I override with UseRedis, everything is getting cached on redis server. I just want to cache custom tables on redis and rest all remains as is. That is, rest of the abp tables should be cached in-memory

  • User Avatar
    0
    maliming created
    Support Team

    You can resolve AbpRedisCacheOptions and then modify the ConnectionString.

    var options = iocManager.Resolve<AbpRedisCacheOptions>()
    options.ConnectionString = ...;
    
  • User Avatar
    0
    sumitshah created

    Thank you, but could you please explain how and where this needs to be implemented. If would be very helpful if you could share a code snippet for the implementation.

    Also, say if I cache a 1000 rows of a SQL table and all the consequent requests are catered from the cache. Now, the admin adds 2 more rows to the table, when and how can we refresh the cache so that the end users always get the fresh data.

  • User Avatar
    0
    ismcagdas created
    Support Team

    For updating cahce, you can use Domain Events https://aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events and in that event, you can update the cace.

    You can configure the connectionString in the PreInitialize method of your web module.