无限的 Redis 客户端循环和 StackOverflow
Infinite Redis Client loop and StackOverflow
我有一个奇怪的事情,直到现在都找不到解决办法。
我们使用 4 个 Redis 服务器(主服务器和从服务器)。
无法在 Redis 上获取我的对象,即使这个对象存在。请帮忙!
我是 Redis 注册用户。
请观看我解释问题的视频:
这是我的代码:
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;
}
请阅读 ServiceStack.Redis 上的文档,RedisManager 或 RedisSentinel
应该只有 1 个单例实例,您应该只在启动时创建一次。
所以我建议将其更改为仅创建 RedisSentinel
和 IRedisClientsManager
的 1 个实例,您可以在静态变量中维护它们。
不清楚您为什么要递归调用自己,并且您提供的代码不会重现此问题,但我希望调用堆栈会揭示问题所在,这可能与 class 您尝试反序列化的通用 T
类型的定义。
注意:为了使这种情况发生,需要再次调用 GetRedisCache<T>()
,这与不了解您的 GetRedisCache<T>()
方法的 Redis 客户端无关,唯一的事情它试图做的是反序列化 T
的一个实例,所以我会查看反序列化中获得 运行 的任何代码,因为其他东西最终会直接或间接地再次调用你自己。我会检查你的调用堆栈,看看导致这个的代码路径是什么。
我有一个奇怪的事情,直到现在都找不到解决办法。
我们使用 4 个 Redis 服务器(主服务器和从服务器)。
无法在 Redis 上获取我的对象,即使这个对象存在。请帮忙!
我是 Redis 注册用户。
请观看我解释问题的视频:
这是我的代码:
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;
}
请阅读 ServiceStack.Redis 上的文档,RedisManager 或 RedisSentinel
应该只有 1 个单例实例,您应该只在启动时创建一次。
所以我建议将其更改为仅创建 RedisSentinel
和 IRedisClientsManager
的 1 个实例,您可以在静态变量中维护它们。
不清楚您为什么要递归调用自己,并且您提供的代码不会重现此问题,但我希望调用堆栈会揭示问题所在,这可能与 class 您尝试反序列化的通用 T
类型的定义。
注意:为了使这种情况发生,需要再次调用 GetRedisCache<T>()
,这与不了解您的 GetRedisCache<T>()
方法的 Redis 客户端无关,唯一的事情它试图做的是反序列化 T
的一个实例,所以我会查看反序列化中获得 运行 的任何代码,因为其他东西最终会直接或间接地再次调用你自己。我会检查你的调用堆栈,看看导致这个的代码路径是什么。