简体   繁体   English

为 StackExchange.Redis 实现最小负载连接的问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM