StackExchange.Redis. Is it possible to prioritize endpoints?

My setup:

  • 4 windows server
  • Redis Node and the Sentinel process on each server.
  • The same web application hosted on each of these servers
  • The web application connects to redis servers through the StackExchange.Redis driver.

Everything works fine, but I wonder if it is possible for read operations to always try to use the redis Node, which is locally available first. This would greatly improve performance since there would be fewer transitions for all read operations.

As far as I can see, you can prioritize subordinates over masters for specific commands using the Command Flags property. But is there a way to prioritize specific endpoints ?

PS:

Used DLL: StackExchange.Redis.StrongName@1.2.0.0

Redis Server Version: 3.2.100

EDIT:

Here is my connection code. The reason I didn’t use the recommended Lazy getter was because I wanted to connect / reconnect to a failure of one of the nodes, which works very well with my solution.

internal class RedisConnector
{
    private readonly ConfigurationOptions _currentConfiguration;
    internal ConnectionMultiplexer Connection;

    internal RedisCacheStore Store;

    internal RedisConnector(ConfigurationOptions configuration)
    {
        _currentConfiguration = configuration;
        Connect();
    }

    internal IDatabase Database
        => Connection.GetDatabase(RedisCacheConfiguration.Instance.Connection.DatabaseId);

    internal IServer Server => Connection.GetServer(Database.IdentifyEndpoint());

    private void Connect()
    {
        Connection = ConnectionMultiplexer.Connect(_currentConfiguration);
        if (Connection == null || !Connection.IsConnected)
            throw new CacheNotAvailableException();
        Connection.ConnectionFailed += OnConnectionFailed;
        Connection.ConnectionRestored += OnConnectionRestored;
        Store = new RedisCacheStore(Database);
    }

    private void Reconnect()
    {
        if (Connection != null && !Connection.IsConnected)
            Connection.Dispose();
        Connect();
    }

    private void OnConnectionFailed(object sender, ConnectionFailedEventArgs args)
    {
        lock (_currentConfiguration)
        {
            if (_currentConfiguration.EndPoints.Contains(args.EndPoint))
            {
                _currentConfiguration.EndPoints.Remove(args.EndPoint);
                Reconnect();
            }
        }
    }

    private void OnConnectionRestored(object sender, ConnectionFailedEventArgs args)
    {
        lock (_currentConfiguration)
        {
            if (!_currentConfiguration.EndPoints.Contains(args.EndPoint))
            {
                _currentConfiguration.EndPoints.Add(args.EndPoint);
                Reconnect();
            }
        }
    }
}
+4
source share
1 answer

in this case.

Let's say you have this case, 3VM with 3 applications and 3 redis instances.
enter image description here The best option for APP running on VM1 is to use Redis on VM1. The best option for APP running in VM2 is to use Redis in VM2. The best option for APP running in VM3 is to use Redis in VM3.

:

private static Lazy<ConfigurationOptions> configOptions
    = new Lazy<ConfigurationOptions>(() => 
    {
        var configOptions = new ConfigurationOptions();
        configOptions.EndPoints.Add("x.x.x.1:6379");          
        configOptions.EndPoints.Add("x.x.x.2:6379");
        configOptions.EndPoints.Add("x.x.x.3:6379");

        configOptions.ClientName = "LeakyRedisConnection";
        configOptions.ConnectTimeout = 100000;
        configOptions.SyncTimeout = 100000;
        return configOptions;
    });



private static string getIP()
{
    var host = Dns.GetHostEntry(Dns.GetHostName());
    foreach (var ip in host.AddressList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork)
        {
            return ip.ToString();
        }
    }
    throw new Exception("ip not found!");
}


private static Lazy<ConfigurationOptions> getOptionsForIp(string myip)
        {
            var configOptions = new ConfigurationOptions();
            configOptions.EndPoints.Add(myip);
            configOptions.ClientName = "LeakyRedisConnectionDirectVM";
            configOptions.ConnectTimeout = 100000;
            configOptions.SyncTimeout = 100000;
            return configOptions;
        });


private static ConnectionMultiplexer conn;

private static ConnectionMultiplexer LeakyConn
{
    get
    {
        if (conn == null || !conn.IsConnected){               
            string myIP = getIP();

            conn = ConnectionMultiplexer.Connect(getOptionsForIp(myIP).Value);
            if(conn == null || !conn.IsConnected){
                conn = ConnectionMultiplexer.Connect(configOptions.Value);
            }

        }
        return conn;
    }
}

:

 var db = LeakyConn.GetDatabase();
 db.StringSet(key, i);
 db.StringGet(key);
+1

Source: https://habr.com/ru/post/1678265/


All Articles