Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis, StackExchange, work with MGET, get many keys at once

Is there a way to use MGET with StackExchange Redis (C#) ?

I need a way to reed many keys in one call.

like image 914
Guy Assaf Avatar asked Nov 08 '16 15:11

Guy Assaf


Video Answer


2 Answers

It is possible to use the next method

 Task<RedisValue[]> StringGetAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None);

In the DLL of StackExchange. Give an array of Keys and receive an Array of Redis values.

like image 131
Guy Assaf Avatar answered Dec 16 '22 07:12

Guy Assaf


You can use StringGetAsync, but it may lead you to overloading your server in case of huge amount of keys. You can use the function from below that will fetch all the keys with paging by 50000 keys per page

public async Task<Dictionary<string, T>> GetManyAsync<T>(ICollection<string> ids, int dbIndex)
{
        var semaphore = new SemaphoreSlim(1);
        var rs = await ids.ToRedisKeys()
            .ToObservable()
            .Buffer(50000)
            .SelectMany(async keysPage =>
            {
                try
                {
                    await semaphore.WaitAsync();
                    var redisValues = await DoRead(_ => _.StringGetAsync(keysPage.ToArray()), dbIndex);
                    return redisValues.Select(_ => serializer.Deserialize<T>(_));
                }
                finally
                {
                    semaphore.Release();
                }
            }).SelectMany(_ => _).ToList();
        return ids.Zip(rs, (i, r) => new { i, r }).ToDictionary(_ => _.i, _ => _.r);
}

Test for this function:

    [Fact]
    public async Task test_redis_paging()
    {
        var source = Observable.Range(1, 5);
        var kvp = await source.Buffer(3).SelectMany(async ls =>
         {
             string msg = $"item: {ls.First()}; thread {Thread.CurrentThread.ManagedThreadId}";
             Console.Out.WriteLine(DateTime.Now.TimeOfDay + msg + " started:");
             await Task.Delay(1000);
             Console.Out.WriteLine(DateTime.Now.TimeOfDay + msg + " finished:");

             return ls;

         }).SelectMany(_=>_).ToList();
         (kvp.Count()).Should().Be(5);
    }
like image 45
Arkhangelskiy Evgeniy Avatar answered Dec 16 '22 07:12

Arkhangelskiy Evgeniy