Is there a way to use MGET with StackExchange Redis (C#) ?
I need a way to reed many keys in one call.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With