@mgravell have set up a redis cluster and using your code example and set up the end points and trying to add to it and getting the following error:
StackExchange.Redis.RedisServerException - MOVED 2852 127.0.0.1:7001
Seems like we are connected as a single instance and not as a cluster with the "-c" parameter, how does one do this?
@mgravell, how do you handle the MOVED exception in your code? We downloaded the code and looking through it we couldn't understand how the message is redirected to the new master. We thought that the logic that handle this is not being called on the communication protocol.
Could you clarify a little bit how this worked?
This should be handled internally. However, I have not had chance to
validate against recent cluster builds, so it is possible a cog has fallen
out. I'm on vacation at the moment, but when I get back I'll try to set up
a vCurrent cluster and check.
On Wed, 12 Aug 2015 16:31 vlavellauruit [email protected] wrote:
@mgravell https://github.com/mgravell, how do you handle the MOVED
exception in your code? We downloaded the code and looking through it we
couldn't understand how the message is redirected to the new master. We
thought that the logic that handle this is not being called on the
communication protocol.
Could you clarify a little bit how this worked?â
Reply to this email directly or view it on GitHub
https://github.com/StackExchange/StackExchange.Redis/issues/248#issuecomment-130322564
.
Hi @mgravell
I am also facing the same issue.
Did u get any chance to look into this issue
@debbiswal, please check the new version of master. @leosvelperez did a pull request that solved a part of the problem.
Keep in mind that MOVED exception is the way that the server notified the change on the slots. You could still getting some exceptions, and should handle that in your code.
Regards
Thanks @vlavellauruit ..
I have downloaded the new codebase(@leosvelperez changes). But still I am getting the same issue.
Just wanted to know what are u expecting me to do when I get this exception.
Below is the console application where I am trying to first read , then set new value , then again read.
On every get or set exception is handled and a retry is happening.
For me some times on 1st try I am able to get/set value
or
Getting MOVED exception on 1st try and on 2nd try able to get/set value
or
Getting MOVED exception on both1st try and on 2nd try
Here port 7001,7002,7003 are masters and
7004(slave of 7001),7005(slave of 7002) , 7006(slave of 7003)
CODE :
class Program
{
const string hostPort =
"127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,
127.0.0.1:7006,allowAdmin=true,connectTimeout=90000";
static readonly Object Lock = new Object();
static ConnectionMultiplexer _connection;
static ConnectionMultiplexer Connection
{
get
{
lock (Lock)
{
if (_connection == null || !_connection.IsConnected)
{
//kill old connection
if (_connection != null)
{
_connection.Close(false);
_connection.Dispose();
_connection = null;
}
_connection = ConnectionMultiplexer.Connect(hostPort);
}
return _connection;
}
}
}
static void Main(string[] args)
{
IDatabase db = Connection.GetDatabase();
string key = string.Empty;
string value = string.Empty;
string choice = "y";
while (choice.ToLower() == "y")
{
Console.WriteLine("Enter key");
key = Console.ReadLine();
Console.WriteLine("==================================================");
Console.WriteLine("Trying to get existing values (if any)");
try
{
value = db.StringGet(key);
Console.WriteLine("1st try:GET " + key + " = " + value);
}
catch (Exception ex)
{
Console.WriteLine("1st try:Unable to get " + ex.Message);
try
{
value = db.StringGet(key);
Console.WriteLine("2nd try:GET " + key + " = " + value);
}
catch (Exception ex1)
{
Console.WriteLine("2nd try :Unable to get " + ex1.Message);
}
}
Console.WriteLine("================================================");
Console.WriteLine("Trying to set values ");
value = "Value " + System.DateTime.Now.ToString();
try
{
db.StringSet(key, value);
Console.WriteLine("1st try:SET " + key + " = " + value);
}
catch (Exception ex)
{
Console.WriteLine("1st try:Unable to set " + ex.Message);
try
{
db.StringSet(key, value);
Console.WriteLine("2nd try:SET " + key + " = " + value);
}
catch (Exception ex1)
{
Console.WriteLine("2nd try:Unable to set " + ex1.Message);
}
}
Console.WriteLine("======================================================");
Console.WriteLine("Trying to get existing values (if any)");
value = "BLANK";
try
{
value = db.StringGet(key);
Console.WriteLine("1st try:GET " + key + " =" + value);
}
catch (Exception ex)
{
Console.WriteLine("1st try:Unable to get " + ex.Message);
try
{
value = db.StringGet(key);
Console.WriteLine("2nd try:GET " + key + " = " + value);
}
catch (Exception ex1)
{
Console.WriteLine("2nd try :Unable to get " + ex1.Message);
}
}
Console.WriteLine("Do you want to continue [Y/N]");
choice = Console.ReadLine();
}
}
}
@mgravell , @vlavellauruit , @leosvelperez : could you pls help on this.
Hi @mgravell , @vlavellauruit , @leosvelperez,
With slight change in code for 2nd try(in my previous post ) , I have managed to do the set /get.
What I have done is , If I am getting the 'MOVED' error , I am opening a new connection with specified port(from exception) to get the value. I am not sure whether this approach is the correct one and what is the overhead in production env. Pls suggest .
Below is the sample code :
try
{
value = db.StringGet(key);
Console.WriteLine("1st try:GET " + key + " = " + value);
}
catch (Exception ex)
{
Console.WriteLine("1st try:Unable to get " + ex.Message);
try
{
ConnectionMultiplexer con = ConnectionMultiplexer.Connect("127.0.0.1:" + ex.Message.Split(':')[1]);
IDatabase db2 = con.GetDatabase();
value = db2.StringGet(key);
Console.WriteLine("2nd try:GET " + key + " = " + value);
con.Close();
con.Dispose();
con = null;
}
catch (Exception ex1)
{
Console.WriteLine("2nd try :Unable to get " + ex1.Message);
}
}
A change was merged recently that should address the "MOVED" error. Have
you tried with the latest code?
On 3 September 2015 at 12:35, debbiswal [email protected] wrote:
Hi @mgravell https://github.com/mgravell , @vlavellauruit
https://github.com/vlavellauruit , @leosvelperez
https://github.com/leosvelperez,With slight change in code for 2nd try(in my previous post ) , I have
managed to do the set /get.
What I have done is , If I am getting the 'MOVED' error , I am opening a
new connection with specified port(from exception) to get the value. I am
not sure whether this approach is the correct one and what is the overhead
in production env. Pls suggest .
Below is the sample code :
try
{
value = db.StringGet(key);
Console.WriteLine("1st try:GET " + key + " = " + value);
}catch (Exception ex) { Console.WriteLine("1st try:Unable to get " + ex.Message); try { ConnectionMultiplexer con = ConnectionMultiplexer.Connect("127.0.0.1:" + ex.Message.Split(':')[1]); IDatabase db2 = con.GetDatabase(); value = db2.StringGet(key); Console.WriteLine("2nd try:GET " + key + " = " + value); con.Close(); con.Dispose(); con = null; } catch (Exception ex1) { Console.WriteLine("2nd try :Unable to get " + ex1.Message); } }â
Reply to this email directly or view it on GitHub
https://github.com/StackExchange/StackExchange.Redis/issues/248#issuecomment-137413219
.
Regards,
Marc
Yes @mgravell. I tried the latest code change done by @leosvelperez.But still getting the same MOVED exception.. so I tried the fallback scenario... But could you pls tell me .. whether my approach is correct.. as @vlavellauruit replied to my post she is telling some times the exception is still comming and we have to handle it in our code. So is that means we have to retry with new connection to get the value(what ever i did in 2nd try)...?
Hi @mgravell / @vlavellauruit / @leosvelperez,
In my scenario I shutdown master 7001 so 7004 is promoted to master. Now 7002,7003,7004 are masters where as 7005,7006 are slaves of 7002,7003.
I am getting 'MOVED 4466 127.0.0.1:7003' for a given key.
Below is the logfile details :
127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006,allowAdmin=True,connectTimeout=90000
Connecting 127.0.0.1:7001/Interactive...
BeginConnect: 127.0.0.1:7001
Connecting 127.0.0.1:7002/Interactive...
BeginConnect: 127.0.0.1:7002
Connecting 127.0.0.1:7003/Interactive...
BeginConnect: 127.0.0.1:7003
Connecting 127.0.0.1:7004/Interactive...
BeginConnect: 127.0.0.1:7004
Connecting 127.0.0.1:7005/Interactive...
BeginConnect: 127.0.0.1:7005
Connecting 127.0.0.1:7006/Interactive...
BeginConnect: 127.0.0.1:7006
6 unique nodes specified
EndConnect: 127.0.0.1:7002
Requesting tie-break from 127.0.0.1:7001 > __Booksleeve_TieBreak...
Connected Interactive/127.0.0.1:7002
Server handshake
Requesting tie-break from 127.0.0.1:7002 > __Booksleeve_TieBreak...
Requesting tie-break from 127.0.0.1:7003 > __Booksleeve_TieBreak...
Requesting tie-break from 127.0.0.1:7004 > __Booksleeve_TieBreak...
Setting client name: MyComputer
Requesting tie-break from 127.0.0.1:7005 > __Booksleeve_TieBreak...
Requesting tie-break from 127.0.0.1:7006 > __Booksleeve_TieBreak...
Allowing endpoints 00:01:30 to respond...
Awaiting task completion, IOCP: (Busy=1,Free=999,Min=2,Max=1000), WORKER: (Busy=3,Free=32764,Min=2,Max=32767)
Auto-configure...
Sending critical tracer: Interactive/127.0.0.1:7002
Writing to Interactive/127.0.0.1:7002: ECHO
Flushing outbound buffer
Starting poll
EndConnect: 127.0.0.1:7003
Connected Interactive/127.0.0.1:7003
Server handshake
Setting client name: MyComputer
Auto-configure...
Sending critical tracer: Interactive/127.0.0.1:7003
Writing to Interactive/127.0.0.1:7003: ECHO
Flushing outbound buffer
Starting poll
Connect complete: 127.0.0.1:7002
EndConnect: 127.0.0.1:7004
Connected Interactive/127.0.0.1:7004
Server handshake
Setting client name: MyComputer
Auto-configure...
Sending critical tracer: Interactive/127.0.0.1:7004
Writing to Interactive/127.0.0.1:7004: ECHO
Flushing outbound buffer
Starting poll
Connect complete: 127.0.0.1:7003
EndConnect: 127.0.0.1:7005
Connected Interactive/127.0.0.1:7005
Server handshake
Setting client name: MyComputer
Auto-configure...
Sending critical tracer: Interactive/127.0.0.1:7005
Writing to Interactive/127.0.0.1:7005: ECHO
Flushing outbound buffer
Starting poll
Connect complete: 127.0.0.1:7005
EndConnect: 127.0.0.1:7006
Connected Interactive/127.0.0.1:7006
Server handshake
Setting client name: MyComputer
Auto-configure...
Sending critical tracer: Interactive/127.0.0.1:7006
Writing to Interactive/127.0.0.1:7006: ECHO
Flushing outbound buffer
Starting poll
Connect complete: 127.0.0.1:7006
Connect complete: 127.0.0.1:7004
Response from Interactive/127.0.0.1:7003 / ECHO: BulkString: 16 bytes
Response from Interactive/127.0.0.1:7002 / ECHO: BulkString: 16 bytes
Response from Interactive/127.0.0.1:7005 / ECHO: BulkString: 16 bytes
Response from Interactive/127.0.0.1:7006 / ECHO: BulkString: 16 bytes
Response from Interactive/127.0.0.1:7004 / ECHO: BulkString: 16 bytes
Writing to Interactive/127.0.0.1:7003: GET __Booksleeve_TieBreak
Writing to Interactive/127.0.0.1:7002: GET __Booksleeve_TieBreak
Writing to Interactive/127.0.0.1:7002: PING
Writing to Interactive/127.0.0.1:7005: GET __Booksleeve_TieBreak
Writing to Interactive/127.0.0.1:7005: PING
Writing to Interactive/127.0.0.1:7006: GET __Booksleeve_TieBreak
Writing to Interactive/127.0.0.1:7006: PING
Writing to Interactive/127.0.0.1:7003: PING
Writing to Interactive/127.0.0.1:7004: GET __Booksleeve_TieBreak
Writing to Interactive/127.0.0.1:7004: PING
Response from Interactive/127.0.0.1:7005 / GET __Booksleeve_TieBreak: (null)
Response from Interactive/127.0.0.1:7005 / PING: SimpleString: PONG
Response from Interactive/127.0.0.1:7002 / GET __Booksleeve_TieBreak: (null)
Response from Interactive/127.0.0.1:7002 / PING: SimpleString: PONG
Response from Interactive/127.0.0.1:7003 / GET __Booksleeve_TieBreak: Error: MOVED 6202 127.0.0.1:7002
Response from Interactive/127.0.0.1:7003 / PING: SimpleString: PONG
Response from Interactive/127.0.0.1:7006 / GET __Booksleeve_TieBreak: Error: MOVED 6202 127.0.0.1:7002
Response from Interactive/127.0.0.1:7006 / PING: SimpleString: PONG
Response from Interactive/127.0.0.1:7004 / GET __Booksleeve_TieBreak: Error: MOVED 6202 127.0.0.1:7002
Response from Interactive/127.0.0.1:7004 / PING: SimpleString: PONG
EndConnect: 127.0.0.1:7001
All tasks completed cleanly, IOCP: (Busy=3,Free=997,Min=2,Max=1000), WORKER: (Busy=3,Free=32764,Min=2,Max=32767)
127.0.0.1:7001 faulted: SocketFailure on PING
127.0.0.1:7002 returned with success
127.0.0.1:7003 returned with success
127.0.0.1:7004 returned with success
127.0.0.1:7005 returned with success
127.0.0.1:7006 returned with success
Cluster: 16384 of 16384 slots covered
127.0.0.1:7001: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: Connecting; not in use: DidNotRespond
127.0.0.1:7001: int ops=0, qu=0, qs=0, qc=2, wr=0, sync=2, socks=2; sub ops=0, qu=0, qs=0, qc=0, wr=0, socks=2
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub: 0 (0.00 ops/s; spans 10s)
127.0.0.1:7002: Cluster v3.0.2, master; 16 databases; keep-alive: 00:01:00; int: ConnectedEstablished; sub: ConnectedEstablished, 1 active
127.0.0.1:7002: int ops=12, qu=0, qs=0, qc=0, wr=0, sync=10, async=2, socks=1; sub ops=3, qu=0, qs=0, qc=0, wr=0, subs=1, sync=3, socks=1
Circular op-count snapshot; int: 0+12=12 (1.20 ops/s; spans 10s); sub: 0+3=3 (0.30 ops/s; spans 10s)
127.0.0.1:7003: Cluster v3.0.2, master; 16 databases; keep-alive: 00:01:00; int: ConnectedEstablished; sub: ConnectedEstablished, 1 active
127.0.0.1:7003: int ops=12, qu=0, qs=0, qc=0, wr=0, sync=10, async=2, socks=1; sub ops=3, qu=0, qs=0, qc=0, wr=0, subs=1, sync=3, socks=1
Circular op-count snapshot; int: 0+12=12 (1.20 ops/s; spans 10s); sub: 0+3=3 (0.30 ops/s; spans 10s)
127.0.0.1:7004: Cluster v3.0.2, master; 16 databases; keep-alive: 00:01:00; int: ConnectedEstablished; sub: ConnectedEstablished, 1 active
127.0.0.1:7004: int ops=12, qu=0, qs=0, qc=0, wr=0, sync=10, async=2, socks=1; sub ops=3, qu=0, qs=0, qc=0, wr=0, subs=1, sync=3, socks=1
Circular op-count snapshot; int: 0+12=12 (1.20 ops/s; spans 10s); sub: 0+3=3 (0.30 ops/s; spans 10s)
127.0.0.1:7005: Cluster v3.0.2, slave; 16 databases; keep-alive: 00:01:00; int: ConnectedEstablished; sub: ConnectedEstablished, 1 active
127.0.0.1:7005: int ops=13, qu=0, qs=0, qc=0, wr=0, sync=11, async=2, socks=1; sub ops=3, qu=0, qs=0, qc=0, wr=0, subs=1, sync=3, socks=1
Circular op-count snapshot; int: 0+13=13 (1.30 ops/s; spans 10s); sub: 0+3=3 (0.30 ops/s; spans 10s)
127.0.0.1:7006: Cluster v3.0.2, slave; 16 databases; keep-alive: 00:01:00; int: ConnectedEstablished; sub: ConnectedEstablished, 1 active
127.0.0.1:7006: int ops=13, qu=0, qs=0, qc=0, wr=0, sync=11, async=2, socks=1; sub ops=3, qu=0, qs=0, qc=0, wr=0, subs=1, sync=3, socks=1
Circular op-count snapshot; int: 0+13=13 (1.30 ops/s; spans 10s); sub: 0+3=3 (0.30 ops/s; spans 10s)
127.0.0.1:7003: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7003: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
127.0.0.1:7004: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7004: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
127.0.0.1:7002: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7002: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
127.0.0.1:7006: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7006: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
127.0.0.1:7005: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7005: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
127.0.0.1:7001: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: n/a
127.0.0.1:7001: int ops=0, qu=0, qs=0, qc=0, wr=0, socks=1; sub ops=0, qu=0, qs=0, qc=0, wr=0
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub:
Sync timeouts: 0; fire and forget: 0; last heartbeat: -1s ago
Starting heartbeat...
Connect complete: 127.0.0.1:7001
Hi @mgravell / @vlavellauruit / @leosvelperez,
Finally I got my program working. Thanks to @hrishi18pathak .
I have downloaded the code from https://github.com/hrishi18pathak/StackExchange.Redis/tree/SEClusteringBugFix branch with changes from 17-July-2015. The main changes are in ConnectionMultiplexer and ConfigurartionOptions class.
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);
}
}
}
///
/// 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));
}
internal bool HasAllDnsEndPoints()
{
return !endpoints.Any(ep => !(ep is DnsEndPoint));
}
Still I need to verify for any implications with this fix.
Hello Debbiswal
I noticed that you are using this fix inside your SE.Redis client. However, this has not been merged into the official repository, since I decided to close the pull request associated with this change before it got merged. The reason i closed this pull request was that i found a bug in the SE.Redis behavior after applying this change when the user specifies only a single endpoint in the ConfigurationOptions. I did not get a chance to find the root cause of this failure because of my change. After reverting back the change above, SE.Redis was able connect successfully to the cluster with a single endpoint configuration. So I would advise against using this fix
Thanks
We are still seeing this issue as of today on the code in the master branch. For our repro, it seems to be some type of race condition in the connection initialization logic. If we put a 1 second sleep in our code right after connecting but before using the connection, the issue goes away. Without that sleep, the issue reproduces VERY consistently
Sample code to reproduce:
Repro NuGet Package Version: 1.0.481
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;
namespace ClusterTest
{
class Program
{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect("contoso5clustering.redis.cache.windows.net,abortConnect=false,ssl=true,password=XXX");
});
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
static void Main(string[] args)
{
IDatabase cache = Connection.GetDatabase();
// Perform cache operations using the cache object...
// Simple put of integral data types into the cache
cache.StringSet("key1", "value");
cache.StringSet("key2", 25);
// Simple get of data types from the cache
string key1 = cache.StringGet("key1");
int key2 = (int)cache.StringGet("key2");
}
}
}
We looked into this further and it seems that the issue I described above is really the same as issue #300, which has proposed fix in pull request #312
This should be resolved in 1.1.553-alpha (latest), after #312 was merged in.
I'm using 1.1.572-alpha and this is still an issue. BTW, Microsoft is recommending putting a Thread.Sleep(1000) before returning the ConnectionMultiplexer on their Azure Redis FAQ page to work around this. This does actually seem to "fix" he problem.
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
// Connect to the Redis cache for the first time
var connection = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
// Wait for 1 second
Thread.Sleep(1000);
// Return the connected ConnectionMultiplexer
return connection;
});
Would be nice to get this resolved so folks don't have to resort to such a hacky workaround. Thanks for all your work on this.
We are using 1.1.572-alpha too, on-prem Redis Cluster, and the issue (MOVED Exception) is still present. Microsoft's recommendation to have Thread.Sleep(1000) before returning the ConnectionMultiplexer, seem to be a workaround. Appreciate all your work. Thank you.
I am not sure if anyone that sitll has the issue is on Azure, but in our case Redis cluster was misconfigured when provisioned. MS had to update our configuration to return a local IP and not the VIP when running Redis cluster in a local VNET.
i am facing same issue with 'StackExchange.Redis 1.1.603' build.
I've updated to 1.1.603, and I am facing same issue too. Our redis cluster has 6 master with 12 slave.
sorry, my bad.
i found the reason, when i create the cluster, use command like this:
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002
so i recreate the cluster use:
./redis-trib.rb create --replicas 1 192.168.2.168:7000 192.168.2.168:7001 192.168.2.168:7002
i think the ip of the node is also 127.0.0.1, so can't get connection and retry and giving moved exceptioin.
it works.
When one of the masters is down, the moved exceptions are starting to occur. But the cluster is not down, only one master is down, and its slave becomes master. I'm using 1.1.603. I've tried Thread.Sleep(1000) after Connect, but this didn't fix the issue.
By the way, is the support of redis cluster, for production? We've faced this moved exceptions and we've started to use single instance in our production environments. But eventually, we must use cluster.
I am also experiencing this exact issue with redis build 3.2.3 configured to cluster mode.
This occurs for 3 master and for 3 masters & 3 salves.
Same moved exception...
We have the same issue. The Thread.Sleep workaround above seems to fix it, but that's just horrible.
The MOVED redirects were fixed in later releases - going to close this out to cleanup. If anyone's still seeing this in 1.2.6, please let me know as that's a new issue we're unaware of!
i am having the same issue using the following code
**string connectionString = "localhost:7000,localhost:7001,localhost:7002,localhost:7003,localhost:7004,localhost:7005,allowAdmin=true";
var serializer = new NewtonsoftSerializer();
cacheClient = new StackExchangeRedisCacheClient(serializer, connectionString);
Thread.Sleep(10000);
clientName = cacheClient.Database.Multiplexer.ClientName;**
Thread.sleep didnt help, how else can we fix that?
My redis cluster is runing inside a container on docker. single node works fine - only cluster having MOVED.
Most helpful comment
When one of the masters is down, the moved exceptions are starting to occur. But the cluster is not down, only one master is down, and its slave becomes master. I'm using 1.1.603. I've tried Thread.Sleep(1000) after Connect, but this didn't fix the issue.