Acho que você está se confundindo aqui.
ConnectionMultiplexer
não "bloqueia". Criando um ConnectionMultiplexer
lhe dá um objeto tipo fábrica com o qual você pode criar IDatabase
instâncias. Em seguida, você usa essas instâncias para realizar consultas Redis normais. Você também pode fazer consultas Redis com o próprio multiplexador de conexão, mas essas são consultas de servidor e dificilmente serão feitas com frequência.Então, para resumir, pode ajudar tremendamente ter um conjunto de multiplexadores de conexão, independentemente da sincronização /async/uso misto.
Para expandir ainda mais, aqui está uma implementação de pool muito simples, que certamente pode ser aprimorada ainda mais:
public interface IConnectionMultiplexerPool
{
Task<IDatabase> GetDatabaseAsync();
}
public class ConnectionMultiplexerPool : IConnectionMultiplexerPool
{
private readonly ConnectionMultiplexer[] _pool;
private readonly ConfigurationOptions _redisConfigurationOptions;
public ConnectionMultiplexerPool(int poolSize, string connectionString) : this(poolSize, ConfigurationOptions.Parse(connectionString))
{
}
public ConnectionMultiplexerPool(int poolSize, ConfigurationOptions redisConfigurationOptions)
{
_pool = new ConnectionMultiplexer[poolSize];
_redisConfigurationOptions = redisConfigurationOptions;
}
public async Task<IDatabase> GetDatabaseAsync()
{
var leastPendingTasks = long.MaxValue;
IDatabase leastPendingDatabase = null;
for (int i = 0; i < _pool.Length; i++)
{
var connection = _pool[i];
if (connection == null)
{
_pool[i] = await ConnectionMultiplexer.ConnectAsync(_redisConfigurationOptions);
return _pool[i].GetDatabase();
}
var pending = connection.GetCounters().TotalOutstanding;
if (pending < leastPendingTasks)
{
leastPendingTasks = pending;
leastPendingDatabase = connection.GetDatabase();
}
}
return leastPendingDatabase;
}
}