Исключение MOVED с Redis Cluster - StackExchange.Redis

Настроил сервер Redis Cluster на сервере Ubuntu 14.0 LTS (VM AZURE) с помощью официального руководства по Redis с IP-адресом без замыкания на себя, как указано в @Marcgravell статья, но получение исключения MOVED для некоторых ключей при использовании клиента Stackexchange.Redis. Привет @Marcgravell, не могли бы вы пролить свет на это. Спасибо.


person Murugan Durai    schedule 13.05.2015    source источник
comment
MOVED должен обрабатываться клиентом, если он находится в кластерном режиме. Может быть, вы подключаетесь к экземпляру, используя метод, предназначенный для подключения к одному мастеру?   -  person antirez    schedule 14.05.2015
comment
Привет @antirez, спасибо за ответ и отличный продукт. Мой клиент — Stackexchange.Redis. Да, вы правы, при подключении redis-cli без параметра '-c' я получил исключение. Не знаю, как упомянуть этот параметр строки подключения клиента StackExchange.redis.   -  person Murugan Durai    schedule 14.05.2015
comment
Похоже, что-то чертовски сломалось. мне придется провести повторное расследование   -  person Marc Gravell    schedule 14.05.2015
comment
Привет @Marc Gravell, ты нашел время, чтобы это исправить? Заранее спасибо.   -  person Murugan Durai    schedule 19.05.2015


Ответы (1)


Наконец-то моя программа заработала. Спасибо @hrishi18pathak. Я скачал код с сайта https://github.com/hrishi18pathak/StackExchange.Redis/tree/SEClusteringBugFix с изменениями от 17 июля 2015 г. Основные изменения произошли в классах ConnectionMultiplexer и ConfigurationOptions.


ConnectionMultiplexer.cs (модифицированный метод UpdateClusterRange(), добавлен метод IsNodeCompatibleWithConfiguration()):

internal void UpdateClusterRange(ClusterConfiguration configuration)
    {
        if (configuration == null) return;
        foreach (var node in configuration.Nodes)
        {
            // do not update cluster range if the node configuration is incompatible with the multiplexer 

            // endpoints configuration. If a user has specified endpoints in the multiplexer configuration using

            // Dns endpoints, Stackexchange.redis returns the ConnectionMultiplexer object successfully 
            // after connecting to all the nodes in the connection string (using their host names). 
            // Also, before returning the multiplexer object it updates the mapping of nodes to their clusterslots 

            // and this mapping is of the format “DNS hostname:port” : “clusterSlotNumber”.

            // However at the same time, the client also issues “CLUSTER NODES” command to each of the nodes in the above list 

            // (to determine master and slave configuration) and re-updates the cluster mapping with the output of the clusternodes command 

            // which now is going to contain IP addresses (redis-server itself does not understand host names). 

            // So the cluster mapping is now updated to the format: “IP Address” : “clusterSlotNumber”

            // If the StackExchange.Redis has not been able to connect to all the nodes using their IP addresses by the time the first command (GET,SET) 
            // is issued to the cluster, it results in failure to connect to that particular node resulting in the “MOVED ERROR” 

            // (since it tries to hit a random node in the list subsequently)

            if (node.IsSlave || node.Slots.Count == 0 || !IsNodeCompatibleWithConfiguration(node)) continue;
            foreach (var slot in node.Slots)
            {
                var server = GetServerEndPoint(node.EndPoint);
                if (server != null) serverSelectionStrategy.UpdateClusterRange(slot.From, slot.To, server);
            }
        }
    }

/// <summary>
    /// Checks if the specified node has the same format as that of
    /// the endpoints specified in the multiplexer configuration i.e.
    /// if all nodes are dns endpoints then the specified node has to be a dns endpoint
    /// to be compatible.
    /// </summary>
    /// <param name="node"></param>
    /// <returns>True if node is compatible with multiplexer configuration</returns>
    private bool IsNodeCompatibleWithConfiguration(ClusterNode node)
    {
        return (this.configuration.HasAllDnsEndPoints() && (node.EndPoint is DnsEndPoint)) ||
            (!this.configuration.HasDnsEndPoints() && !(node.EndPoint is DnsEndPoint));
    }

ConfigurationOptions.cs(добавлен метод HasAllDnsEndPoints())

internal bool HasAllDnsEndPoints()
    {
        return !endpoints.Any(ep => !(ep is DnsEndPoint));
    }

Тем не менее мне нужно проверить любые последствия этого исправления.

person Debasis Biswal    schedule 09.09.2015
comment
Было бы неплохо, если бы вы проверили и опубликовали. - person Falaque; 09.09.2015