[英]Problem in implementing least loaded connection for StackExchange.Redis
Based on below answer, I implemented least loaded
connection for StackExchange.Redis
:基于以下答案,我为StackExchange.Redis
实现了least loaded
连接:
https://stackoverflow.com/a/58106770 https://stackoverflow.com/a/58106770
public class RedisConnectionWrapper : IRedisConnectionWrapper
{
#region Fields
private readonly Config _config;
private bool _disposed = false;
private readonly Lazy<string> _connectionString;
private static ConcurrentBag<Lazy<ConnectionMultiplexer>> _connections;
#endregion
#region Ctor
public RedisConnectionWrapper(Config config)
{
_config = config;
_connectionString = new Lazy<string>("CONNECTION_STRING");
ConnectionMultiplexer.SetFeatureFlag("preventthreadtheft", _config.RedisPreventThreadTheft);
if (_config.UseLeastLoadedConnection)
InitializeLeastLoadedConnections();
}
#endregion
/// <summary>
/// Initialize lazy connections to Redis servers
/// </summary>
/// <returns></returns>
private void InitializeLeastLoadedConnections()
{
_connections = new ConcurrentBag<Lazy<ConnectionMultiplexer>>();
for (var i = 0; i < _config.PoolSize; i++)
{
var connection = ConnectionMultiplexer.Connect(_connectionString.Value);
connection.IncludePerformanceCountersInExceptions = true;
_connections.Add(new Lazy<ConnectionMultiplexer>(connection));
}
}
/// <summary>
/// Get least loaded connection to Redis servers
/// </summary>
/// <returns></returns>
protected ConnectionMultiplexer GetLeastLoadedConnection()
{
Lazy<ConnectionMultiplexer> connection;
var loadedLazys = _connections.Where(lazy => lazy.IsValueCreated && lazy.Value.IsConnected);
if (loadedLazys.Count() == _connections.Count)
{
var minValue = _connections.Min(lazy => lazy.Value.GetCounters().TotalOutstanding);
connection = _connections.First(lazy => lazy.Value.GetCounters().TotalOutstanding == minValue);
}
else
{
Console.WriteLine("Creating a new connection to Redis");
connection = _connections.First(lazy => !lazy.IsValueCreated);
}
return connection.Value;
}
/// <summary>
/// Release all resources associated with this object
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
if (_config.UseLeastLoadedConnection)
{
var activeConnections = _connections.Where(lazy => lazy.IsValueCreated).ToList();
activeConnections.ForEach(connection => connection.Value.Dispose());
}
}
_disposed = true;
}
But I'm getting this exception on high traffic:但我在高流量时遇到此异常:
System.InvalidOperationException: Sequence contains no matching element at System.Linq.ThrowHelper.ThrowNoMatchException() at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate) System.InvalidOperationException:序列在 System.Linq.ThrowHelper.ThrowNoMatchException() 处 System.Linq.Enumerable.First[TSource](IEnumerable1 源,Func2 谓词)处不包含匹配元素
Anybody can help me?任何人都可以帮助我吗?
After some traces, I did some changes and it worked:经过一些跟踪,我做了一些更改并且它起作用了:
var loadedLazys = _connections.Where(lazy => lazy.IsValueCreated);
if (loadedLazys.Count() == _connections.Count)
{
connection = _connections.OrderBy(lazy => lazy.Value.GetCounters().TotalOutstanding).First();
}
I changed this part of my code as well:我也更改了代码的这一部分:
private void InitializeLeastLoadedConnections()
{
lock (_lock)
{
_connections = new ConcurrentBag<Lazy<ConnectionMultiplexer>>();
for (var i = 0; i < _config.PoolSize; i++)
{
_connections.Add(new Lazy<ConnectionMultiplexer>(() =>
{
var connection = ConnectionMultiplexer.Connect(_connectionString.Value);
connection.IncludePerformanceCountersInExceptions = true;
return connection;
}));
}
}
}
Also I changed the return type of GetLeastLoadedConnection()
from ConnectionMultiplexer
to IConnectionMultiplexer
.此外,我将GetLeastLoadedConnection()
的返回类型从ConnectionMultiplexer
更改为IConnectionMultiplexer
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.