Redis Cache getting timeout with sync requests and slow response with async requests only in async method

纵然是瞬间 提交于 2019-12-12 12:16:53

问题


First of all I am using Azure Redis Cache service and StackExchange.Redis(1.0.371) client with my MVC 5 and Web Api 2 app. I am getting very interesting behaviors. getting timeout with sync requests and slow response when I convert my sync calling with async. Let me give you an example. Here is my RedisCacheService,

public class RedisCacheService : ICacheService
{
    private readonly IDatabase _cache;
    private static readonly ConnectionMultiplexer ConnectionMultiplexer;

    static RedisCacheService()
    {

        var connection = ConfigurationManager.AppSettings["RedisConnection"];
        ConnectionMultiplexer = ConnectionMultiplexer.Connect(connection);
    }

    public RedisCacheService(ISettings settings)
    {            
        _cache = ConnectionMultiplexer.GetDatabase();
    }

    public bool Exists(string key)
    {
        return _cache.KeyExists(key);
    }

    public Task<bool> ExistsAsync(string key)
    {
        return _cache.KeyExistsAsync(key);
    }


    public void Save(string key, string value, int timeOutInMinutes)
    {
        var ts = TimeSpan.FromMinutes(timeOutInMinutes);
        _cache.StringSet(key, value, ts);
    }

    public Task SaveAsync(string key, string value, int timeOutInMinutes)
    {
        var ts = TimeSpan.FromMinutes(timeOutInMinutes);
        return _cache.StringSetAsync(key, value, ts);
    }

    public string Get(string key)
    {
        return _cache.StringGet(key);
    }

    public async Task<string> GetAsync(string key)
    {
        string result = null;
        var val = await _cache.StringGetAsync(key);
        if(val.HasValue) 
        {
            result = val;
        }
        return result;
    }

    ......................................................................
}

and here is my method which invokes the cache.

public async Task<IList<XX>> GetXXXXX(XXXX)
{
    var key = string.Format("{0}/XX{1}_{2}", XXXX, XX, XX);
    var xxx = _cacheService.Get(key);
    if (xxx != null)
    {
        return JsonConvert.DeserializeObject<IList<XX>>(xxx);
    }
    var x = await _repository.GetXXXXX(XXXXX);
    var contents = JsonConvert.SerializeObject(x);
    _cacheService.Save(key, JsonConvert.SerializeObject(x));
    return x;
}

The above method always gives me,

System.TimeoutException
Timeout performing GET XXX, inst: 0, mgr: Inactive, queue: 3, qu=2, qs=1, qc=0, wr=1/1, in=0/0

or

System.TimeoutException
Timeout performing SETEX XXX, inst: 0, mgr: Inactive, queue: 2, qu=1, qs=1, qc=0, wr=1/1, in=0/0

Let change it to async,

public async Task<IList<XX>> GetXXXXX(XXXX)
{
    var key = string.Format("{0}/XX{1}_{2}", XXXX, XX, XX);
    var xxx = await _cacheService.GetAsync(key);
    if (xxx != null)
    {
        return JsonConvert.DeserializeObject<IList<XX>>(xxx);
    }
    var x = await _repository.GetXXXXX(XXXXX);
    var contents = JsonConvert.SerializeObject(x);
    await  _cacheService.SaveAsync(key, JsonConvert.SerializeObject(x));
    return x;
}

This above method works but it takes at least 5-10 seconds. I mean 10 seconds if no cache is available and 5 seconds if cache is available.

Now lets make my method completely sync,

public async Task<IList<XX>> GetXXXXX(XXXX)
{
    var key = string.Format("{0}/XX{1}_{2}", XXXX, XX, XX);
    var xxx = _cacheService.Get(key);
    if (xxx != null)
    {
        return Task.FromResult(JsonConvert.DeserializeObject<IList<XX>>(xxx));
    }
    //var x = await _repository.GetXXXXX(XXXXX);
    var x = (IList<XX>)new List<XX>();
    var contents = JsonConvert.SerializeObject(x);
    _cacheService.Save(key, JsonConvert.SerializeObject(x));
    return Task.FromResult(x);
}

Please note the comment to call a repository method. The above method work instantly, means I get result within less than 1 seconds. Clearly something wrong with Azure or StackExcahge.Redis client.

Update: My last approach(async) is also working like a charm(fast and no error),

public async Task<IList<XX>> GetXXXXX(XXXX)
{
    var key = string.Format("{0}/XX{1}_{2}", XXXX, XX, XX);
    var xxx = await _cacheService.GetAsync(key);
    if (xxx != null)
    {
        return JsonConvert.DeserializeObject<IList<XX>>(xxx);
    }
    //var x = await _repository.GetXXXXX(XXXXX);
    var x = (IList<XX>)new List<XX>();
    var contents = JsonConvert.SerializeObject(x);
    await _cacheService.SaveAsync(key, JsonConvert.SerializeObject(x));
    return x;
}

Note that still I have commented the repository code.


回答1:


Looks like these timeouts in Azure might be an open issue.. Have you tried this code against a local (non-Azure) server? Do you get the same results?




回答2:


I have solved timeout issuse in Redis Cache by setting the syncTimeout property in the redis cache connection string

e.g. var conn = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,ssl=true,password=password,syncTimeout=5000");

Reference for connection string properties https://stackexchange.github.io/StackExchange.Redis/Configuration



来源:https://stackoverflow.com/questions/27718453/redis-cache-getting-timeout-with-sync-requests-and-slow-response-with-async-requ

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!