Ich glaube du verwechselst dich hier. ConnectionMultiplexer
wird nicht "geblockt". Erstellen eines ConnectionMultiplexer
gibt Ihnen ein Factory-ähnliches Objekt, mit dem Sie IDatabase
erstellen können Instanzen. Anschließend verwenden Sie diese Instanzen, um normale Redis-Abfragen durchzuführen. Sie können Redis-Abfragen auch mit dem Verbindungsmultiplexer selbst durchführen, aber das sind Serverabfragen und werden wahrscheinlich nicht oft durchgeführt.
Um es kurz zu machen, es kann enorm hilfreich sein, einen Pool von Verbindungsmultiplexern zu haben, unabhängig von der Synchronisierung /async/mixed use.
Zur weiteren Erweiterung hier eine sehr einfache Pool-Implementierung, die sicherlich weiter verbessert werden kann:
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;
}
}