Exemple #1
0
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                var slots    = cmd._flagKey.Select(a => GetClusterSlot(a)).Distinct().ToArray();
                var poolkeys = slots.Select(a => _slotCache.TryGetValue(a, out var trykey) ? trykey : null).Distinct().Where(a => a != null).ToArray();

                if (poolkeys.Length > 1)
                {
                    throw new RedisClientException($"Multiple key slot values not equal: {cmd}");
                }
                var poolkey = poolkeys.FirstOrDefault() ?? _ib.GetKeyFirst();

                var pool = _ib.Get(poolkey);

                if (pool.IsAvailable == false)
                {
                    poolkey = _ib.GetKeys(a => a != null && a.IsAvailable).FirstOrDefault();
                    if (string.IsNullOrEmpty(poolkey))
                    {
                        throw new RedisClientException($"All nodes of the cluster failed to connect");
                    }
                    pool = _ib.Get(poolkey);
                }
                var cli      = pool.Get();
                var rds      = cli.Value.Adapter.GetRedisSocket(null);
                var rdsproxy = DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli));

                rdsproxy._pool = pool;
                return(rdsproxy);
            }
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                var slots    = cmd?._keyIndexes.Select(a => GetClusterSlot(cmd._input[a].ToInvariantCultureToString())).Distinct().ToArray();
                var poolkeys = slots?.Select(a => _slotCache.TryGetValue(a, out var trykey) ? trykey : null).Distinct().Where(a => a != null).ToArray();
                //if (poolkeys.Length > 1) throw new RedisClientException($"CROSSSLOT Keys in request don't hash to the same slot: {cmd}");
                var poolkey = poolkeys?.FirstOrDefault();

goto_getrndkey:
                if (string.IsNullOrEmpty(poolkey))
                {
                    var rndkeys = _ib.GetKeys(v => v == null || v.IsAvailable);
                    if (rndkeys.Any() == false)
                    {
                        throw new RedisClientException($"All nodes of the cluster failed to connect");
                    }
                    poolkey = rndkeys[_rnd.Value.Next(0, rndkeys.Length)];
                }
                var pool = _ib.Get(poolkey);

                if (pool.IsAvailable == false)
                {
                    poolkey = null;
                    goto goto_getrndkey;
                }
                var cli      = pool.Get();
                var rds      = cli.Value.Adapter.GetRedisSocket(null);
                var rdsproxy = DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli));

                rdsproxy._poolkey = poolkey;
                rdsproxy._pool    = pool;
                return(rdsproxy);
            }
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                string[] poolkeys = null;
                if (_redirectRule == null)
                {
                    //crc16
                    var slots = cmd?._keyIndexes.Select(a => ClusterAdapter.GetClusterSlot(cmd._input[a].ToInvariantCultureToString())).Distinct().ToArray();
                    poolkeys = slots?.Select(a => _connectionStrings[a % _connectionStrings.Length]).Select(a => $"{a.Host}/{a.Database}").Distinct().ToArray();
                }
                else
                {
                    poolkeys = cmd?._keyIndexes.Select(a => _redirectRule(cmd._input[a].ToInvariantCultureToString())).Distinct().ToArray();
                }

                if (poolkeys == null)
                {
                    poolkeys = new[] { $"{_connectionStrings[0].Host}/{_connectionStrings[0].Database}" }
                }
                ;
                if (poolkeys.Length > 1)
                {
                    throw new RedisClientException($"CROSSSLOT Keys in request don't hash to the same slot: {cmd}");
                }
                var poolkey  = poolkeys?.FirstOrDefault() ?? $"{_connectionStrings[0].Host}/{_connectionStrings[0].Database}";
                var pool     = _ib.Get(poolkey);
                var cli      = pool.Get();
                var rds      = cli.Value.Adapter.GetRedisSocket(null);
                var rdsproxy = DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli));

                rdsproxy._poolkey = poolkey;
                rdsproxy._pool    = pool;
                return(rdsproxy);
            }
Exemple #4
0
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                if (cmd != null && (_rw_splitting || !_is_single))
                {
                    var cmdset = CommandSets.Get(cmd._command);
                    if (cmdset != null)
                    {
                        if (!_is_single && (cmdset.Status & CommandSets.LocalStatus.check_single) == CommandSets.LocalStatus.check_single)
                        {
                            throw new RedisException($"RedisClient: Method cannot be used in {UseType} mode. You can set \"max pool size=1\", but it is not singleton mode.");
                        }

                        if (_rw_splitting &&
                            ((cmdset.Tag & CommandSets.ServerTag.read) == CommandSets.ServerTag.read ||
                             (cmdset.Flag & CommandSets.ServerFlag.@readonly) == CommandSets.ServerFlag.@readonly))
                        {
                            var rndkeys = _ib.GetKeys(v => v == null || v.IsAvailable && v._policy._connectionStringBuilder.Host != _masterHost);
                            if (rndkeys.Any())
                            {
                                var rndkey  = rndkeys[_rnd.Value.Next(0, rndkeys.Length)];
                                var rndpool = _ib.Get(rndkey);
                                var rndcli  = rndpool.Get();
                                var rndrds  = rndcli.Value.Adapter.GetRedisSocket(null);
                                return(DefaultRedisSocket.CreateTempProxy(rndrds, () => rndpool.Return(rndcli)));
                            }
                        }
                    }
                }
                var poolkey = _masterHost;
                var pool    = _ib.Get(poolkey);
                var cli     = pool.Get();
                var rds     = cli.Value.Adapter.GetRedisSocket(null);

                return(DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli)));
            }
Exemple #5
0
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                var poolkey  = GetIdleBusKey(cmd);
                var pool     = _ib.Get(poolkey);
                var cli      = pool.Get();
                var rds      = cli.Value.Adapter.GetRedisSocket(null);
                var rdsproxy = DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli));

                rdsproxy._pool = pool;
                return(rdsproxy);
            }
Exemple #6
0
            public override IRedisSocket GetRedisSocket(CommandPacket cmd)
            {
                var poolkey = GetIdleBusKey(cmd);

                if (string.IsNullOrWhiteSpace(poolkey))
                {
                    throw new RedisClientException($"【{_connectionString.Host}】Redis Sentinel is switching");
                }
                var pool     = _ib.Get(poolkey);
                var cli      = pool.Get();
                var rds      = cli.Value.Adapter.GetRedisSocket(null);
                var rdsproxy = DefaultRedisSocket.CreateTempProxy(rds, () => pool.Return(cli));

                rdsproxy._poolkey = poolkey;
                rdsproxy._pool    = pool;
                return(rdsproxy);
            }
Exemple #7
0
 public override IRedisSocket GetRedisSocket(CommandPacket cmd)
 {
     return(DefaultRedisSocket.CreateTempProxy(_redisSocket, null));
 }
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                if (cmd._keyIndexes.Count > 1) //Multiple key slot values not equal
                {
                    switch (cmd._command)
                    {
                    case "DEL":
                    case "UNLINK":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());

                    case "MSET":
                        cmd._keyIndexes.ForEach(idx => AdapterCall(cmd._command.InputKey(cmd._input[idx].ToInvariantCultureToString()).InputRaw(cmd._input[idx + 1]), parse));
                        return(default);

                    case "MGET":
                        return(cmd._keyIndexes.Select((_, idx) =>
                        {
                            var rt = AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse);
                            return rt.ConvertTo <object[]>().FirstOrDefault();
                        }).ToArray().ConvertTo <TValue>());

                    case "PFCOUNT":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());
                    }
                }
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    RedisClientPool pool = null;
                    var protocolRetry = false;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                        try
                        {
                            if (cmd._clusterMovedAsking)
                            {
                                cmd._clusterMovedAsking = false;
                                var askingCmd = "ASKING".SubCommand(null).FlagReadbytes(false);
                                rds.Write(askingCmd);
                                rds.Read(askingCmd);
                            }
                            rds.Write(cmd);
                            rt = rds.Read(cmd);
                        }
                        catch (ProtocolViolationException)
                        {
                            rds.ReleaseSocket();
                            cmd._protocolErrorTryCount++;
                            if (cmd._protocolErrorTryCount <= pool._policy._connectionStringBuilder.Retry)
                            {
                                protocolRetry = true;
                            }
                            else
                            {
                                if (cmd.IsReadOnlyCommand() == false || cmd._protocolErrorTryCount > 1)
                                {
                                    throw;
                                }
                                protocolRetry = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw;
                        }
                    }
                    if (protocolRetry)
                    {
                        return AdapterCall(cmd, parse);
                    }
                    if (rt.IsError && pool != null)
                    {
                        var moved = ClusterMoved.ParseSimpleError(rt.SimpleError);
                        if (moved != null && cmd._clusterMovedTryCount < 3)
                        {
                            cmd._clusterMovedTryCount++;

                            if (moved.endpoint.StartsWith("127.0.0.1"))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }
                            else if (moved.endpoint.StartsWith("localhost", StringComparison.CurrentCultureIgnoreCase))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }

                            ConnectionStringBuilder connectionString = pool._policy._connectionStringBuilder.ToString();
                            connectionString.Host = moved.endpoint;
                            RegisterClusterNode(connectionString);

                            if (moved.ismoved)
                            {
                                _slotCache.AddOrUpdate(moved.slot, connectionString.Host, (k1, v1) => connectionString.Host);
                            }

                            if (moved.isask)
                            {
                                cmd._clusterMovedAsking = true;
                            }

                            TopOwner.OnNotice(null, new NoticeEventArgs(NoticeType.Info, null, $"{(cmd.WriteTarget ?? "Not connected").PadRight(21)} > {cmd}\r\n{rt.SimpleError} ", null));
                            return AdapterCall(cmd, parse);
                        }
                    }
                    return parse(rt);
                }));
            }
            void RefershClusterNodes()
            {
                foreach (var testConnection in _clusterConnectionStrings)
                {
                    RegisterClusterNode(testConnection);
                    //尝试求出其他节点,并缓存slot
                    try
                    {
                        var cnodes = AdapterCall <string>("CLUSTER".SubCommand("NODES"), rt => rt.ThrowOrValue <string>()).Split('\n');
                        foreach (var cnode in cnodes)
                        {
                            if (string.IsNullOrEmpty(cnode))
                            {
                                continue;
                            }
                            var dt = cnode.Trim().Split(' ');
                            if (dt.Length < 9)
                            {
                                continue;
                            }
                            if (!dt[2].StartsWith("master") && !dt[2].EndsWith("master"))
                            {
                                continue;
                            }
                            if (dt[7] != "connected")
                            {
                                continue;
                            }

                            var endpoint = dt[1];
                            var at40     = endpoint.IndexOf('@');
                            if (at40 != -1)
                            {
                                endpoint = endpoint.Remove(at40);
                            }

                            if (endpoint.StartsWith("127.0.0.1"))
                            {
                                endpoint = $"{DefaultRedisSocket.SplitHost(testConnection.Host).Key}:{endpoint.Substring(10)}";
                            }
                            else if (endpoint.StartsWith("localhost", StringComparison.CurrentCultureIgnoreCase))
                            {
                                endpoint = $"{DefaultRedisSocket.SplitHost(testConnection.Host).Key}:{endpoint.Substring(10)}";
                            }
                            ConnectionStringBuilder connectionString = testConnection.ToString();
                            connectionString.Host = endpoint;
                            RegisterClusterNode(connectionString);

                            for (var slotIndex = 8; slotIndex < dt.Length; slotIndex++)
                            {
                                var slots = dt[slotIndex].Split('-');
                                if (ushort.TryParse(slots[0], out var tryslotStart) &&
                                    ushort.TryParse(slots[1], out var tryslotEnd))
                                {
                                    for (var slot = tryslotStart; slot <= tryslotEnd; slot++)
                                    {
                                        _slotCache.AddOrUpdate(slot, connectionString.Host, (k1, v1) => connectionString.Host);
                                    }
                                }
                            }
                        }
                        break;
                    }
                    catch
                    {
                        _ib.TryRemove(testConnection.Host, true);
                    }
                }

                if (_ib.GetKeys().Length == 0)
                {
                    throw new RedisClientException($"All \"clusterConnectionStrings\" failed to connect");
                }
            }
Exemple #10
0
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    RedisClientPool pool = null;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                        try
                        {
                            if (cmd._clusterMovedAsking)
                            {
                                cmd._clusterMovedAsking = false;
                                rds.Write("ASKING");
                                rds.Read(false);
                            }
                            rds.Write(cmd);
                            rt = rds.Read(cmd._flagReadbytes);
                        }
                        catch (Exception ex)
                        {
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw ex;
                        }
                    }
                    if (rt.IsError && pool != null)
                    {
                        var moved = ClusterMoved.ParseSimpleError(rt.SimpleError);
                        if (moved != null && cmd._clusterMovedTryCount < 3)
                        {
                            cmd._clusterMovedTryCount++;

                            if (moved.endpoint.StartsWith("127.0.0.1"))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }
                            else if (moved.endpoint.StartsWith("localhost", StringComparison.CurrentCultureIgnoreCase))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }

                            ConnectionStringBuilder connectionString = pool._policy._connectionStringBuilder.ToString();
                            connectionString.Host = moved.endpoint;
                            RegisterClusterNode(connectionString);

                            if (moved.ismoved)
                            {
                                _slotCache.AddOrUpdate(moved.slot, connectionString.Host, (k1, v1) => connectionString.Host);
                            }

                            if (moved.isask)
                            {
                                cmd._clusterMovedAsking = true;
                            }

                            TopOwner.OnNotice(new NoticeEventArgs(NoticeType.Info, null, $"{(cmd.WriteHost ?? "Not connected")} > {cmd}\r\n{rt.SimpleError} ", null));
                            return AdapterCall(cmd, parse);
                        }
                    }
                    rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
                    return parse(rt);
                }));
            }