Tweek Tweek - 2 months ago 37
ASP.NET (C#) Question

Is this a good implementation of StackExchange Redis pipelining?

I'm starting with REDIS and the StackExchange Redis client. I'm wondering if I'm getting the best performance for getting multiple items at once from REDIS.

Situation:
I have an ASP.NET MVC web application that shows a personal calendar on the dashboard of the user. Because the dashboard is the landing page it's heavily used.

To show the calendar items, I first get all calendar item ID's for that particular month:

RedisManager.RedisDb.StringGet("calendaritems_2016_8");
// this returns JSON Serialized List<int>


Then, for each calendar item id I build a list of corresponding cache keys:

"CalendarItemCache_1"
"CalendarItemCache_2"
"CalendarItemCache_3"
etc.


With this collection I reach out to REDIS with a generic function:

var multipleItems = CacheHelper.GetMultiple<CalendarItemCache>(cacheKeys);


That's implemented like:

public List<T> GetMultiple<T>(List<string> keys) where T : class
{
var taskList = new List<Task>();
var returnList = new ConcurrentBag<T>();

foreach (var key in keys)
{
Task<T> stringGetAsync = RedisManager.RedisDb.StringGetAsync(key)
.ContinueWith(task =>
{
if (!string.IsNullOrWhiteSpace(task.Result))
{
var deserializeFromJson = CurrentSerializer.Serializer.DeserializeFromJson<T>(task.Result);
returnList.Add(deserializeFromJson);
return deserializeFromJson;
}
else
{
return null;
}
});
taskList.Add(stringGetAsync);
}
Task[] tasks = taskList.ToArray();
Task.WaitAll(tasks);

return returnList.ToList();
}


Am I implementing pipelining correct? The REDIS CLI monitor shows:

1472728336.718370 [0 127.0.0.1:50335] "GET" "CalendarItemCache_1"
1472728336.718389 [0 127.0.0.1:50335] "GET" "CalendarItemCache_2"
etc.


I'm expecting some kind of MGET command.

Many thanks in advance.

Answer

I noticed an overload method for StringGet that accepts a RedisKey[]. Using this, I see a MGET command in the monitor.

    public List<T> GetMultiple<T>(List<string> keys) where T : class
    {
        List<RedisKey> list = new List<RedisKey>(keys.Count);
        foreach (var key in keys)
        {
            list.Add(key);
        }

        RedisValue[] result = RedisManager.RedisDb.StringGet(list.ToArray());

        var redisValues = result.Where(x=>x.HasValue);
        var multiple = redisValues.Select(x => DeserializeFromJson<T>(x)).ToList();
        return multiple;

    }
Comments