无限Redis客户端循环和StackOverflow

时间:2015-12-04 10:25:30

标签: c# servicestack servicestack.redis

我有一件奇怪的事情,到现在为止找不到解决办法。

我们使用4台Redis服务器(主服务器和从服务器)。

无法在Redis上获取我的对象,即使这个存在。请帮忙!

我是注册的Redis用户。

请在此视频中解释问题:

https://youtu.be/HAem8aqS4yw

这是我的代码:

private static RedisSentinel _redisSentinel;
private static IRedisClientsManager _redisManager;

private static IRedisClientsManager GetRedisSentinel()
{
    try
    {
        if (_redisSentinel == null || _redisManager == null)
        {
            List<string> listSentinels = new List<string>();
            listSentinels.Add(ConfigurationManager.AppSettings["RedisDB1"]);
            listSentinels.Add(ConfigurationManager.AppSettings["RedisDB2"]);
            listSentinels.Add(ConfigurationManager.AppSettings["RedisDB3"]);
            listSentinels.Add(ConfigurationManager.AppSettings["RedisDB4"]);

            _redisSentinel = new RedisSentinel(listSentinels, ConfigurationManager.AppSettings["RedisMaster"])
            {
                OnWorkerError = ex =>
                {
                    _logRedis.Info( "Worker error: {0}" + ex.Message, ex);
                },
                OnFailover = redisClient =>
                {
                    _logRedis.Info("Fail over: {0}" + redisClient);
                    redisClient.Dispose();
                },
                OnSentinelMessageReceived = (s1,s2) =>
                {
                    _logRedis.Info(string.Format("Sentinel message: {0} - {1}", s1, s2));
                }
            };

            _redisSentinel = new RedisSentinel(listSentinels, ConfigurationManager.AppSettings["RedisMaster"]);
            _redisSentinel.RedisManagerFactory = (master, slaves) => new RedisManagerPool(master);
            _redisManager = _redisSentinel.Start();


            _log.Trace("Open REDIS Connection: OK.");
        }


    }
    catch (Exception ex)
    {
        _log.Trace(ex, "Error Redis Connection: " + ex.Message);
    }

    return _redisManager;
}

public static object GetRedisCache<T>(string key)
{
    object myObject = null;

    //naming convention [PLATFORM]:[PROJECT]:[FUNCTION]:[PARAMETERS…]
    string redisKey = string.Format("WEB:{0}:{1}:{2}", _redisProject, typeof (T), key);

    try
    {
        //Open Redis
        IRedisClientsManager redisManager = GetRedisSentinel(); // <- jump -----------<
        if (redisManager != null)
        {

            using (RedisClient redis = (RedisClient) redisManager.GetClient()) 
            {

                //here: the problem occurs, No crash, No Exception
                //just it roll back again to line GetRedisSentinel(), see my video
                myObject = redis.Get<T>(redisKey);  //--> jump directly to ------------^
            }

        }


    }
    catch (Exception ex)
    {
        _log.Trace(ex, "Error Get In Redis: " + ex.Message);
    }

    return myObject;
}

1 个答案:

答案 0 :(得分:1)

请阅读ServiceStack.Redis上的文档,应该只有一个RedisManager或RedisSentinel的单例实例,您应该只在StartUp上创建一次。

因此,我建议将其更改为仅创建一个RedisSentinelIRedisClientsManager的实例,您可以将其保存在静态变量中。

目前尚不清楚为什么你会递归调用自己,你提供的代码不会重现这个问题,但我希望callstack会揭示问题是什么,这可能与泛型的类定义有关{ {1}}键入您正在尝试反序列化。

注意:要发生这种情况,需要再次调用T,这与Redis客户端无关,Redis客户端不了解您的GetRedisCache<T>()方法,它唯一要尝试的方法要做的是反序列化GetRedisCache<T>()的实例,所以我会看看在反序列化时运行的任何代码,因为其他东西最终会直接或间接地再次调用自己。我会检查你的callstack,看看导致这个问题的代码路径是什么。