Guy Assaf
Guy Assaf

Reputation: 971

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.

Upvotes: 9

Views: 7476

Answers (2)

Arkhangelskiy Evgeniy
Arkhangelskiy Evgeniy

Reputation: 622

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);
    }

Upvotes: 2

Guy Assaf
Guy Assaf

Reputation: 971

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.

Upvotes: 16

Related Questions