ConnectionMultiplexer 如何处理断开连接?
How does ConnectionMultiplexer deal with disconnects?
StackExchange.Redis 的 Basic Usage 文档解释说 ConnectionMultiplexer
是长期存在的,预计会被重复使用。
但是当与服务器的连接断开时怎么办? ConnectionMultiplexer
是否自动重新连接,或者是否有必要像 this answer 那样编写代码(引用该答案):
if (RedisConnection == null || !RedisConnection.IsConnected)
{
RedisConnection = ConnectionMultiplexer.Connect(...);
}
RedisCacheDb = RedisConnection.GetDatabase();
上面的代码是否适合处理断开连接的恢复,或者它实际上会导致多个 ConnectionMultiplexer
实例?同样,IsConnected
属性 应该如何解释?
[旁白:我认为上面的代码是一种非常糟糕的惰性初始化形式,尤其是在多线程环境中 - 请参阅 Jon Skeet's article on Singletons]。
是的,您需要这种类型的验证才能修复断开的连接。一些线程安全也应该被考虑在内。这就是我通常这样做的方式:
private static ConnectionMultiplexer _redis;
private static readonly Object _multiplexerLock = new Object();
private void ConnectRedis()
{
try
{
_redis = ConnectionMultiplexer.Connect("...<connection string here>...");
}
catch (Exception ex)
{
//exception handling goes here
}
}
private ConnectionMultiplexer RedisMultiplexer
{
get
{
lock (_multiplexerLock)
{
if (_redis == null || !_redis.IsConnected)
{
ConnectRedis();
}
return _redis;
}
}
}
然后我在需要调用 Redis 端点的任何地方使用 RedisMultiplexer
属性。我通常不存储 GetDatabase()
调用的结果,因为文档说这是一个非常轻量级的调用。
这里是 pattern recommended by the Azure Redis Cache team:
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});
public static ConnectionMultiplexer Connection {
get {
return lazyConnection.Value;
}
}
几个要点:
- 它使用 Lazy
来处理线程安全初始化
- 它设置 "abortConnect=false",这意味着如果初始连接尝试失败,ConnectionMultiplexer 将在后台静默重试而不是抛出异常。
- 它不会检查 IsConnected 属性,因为如果连接断开,ConnectionMultiplexer 将在后台自动重试。
StackExchange.Redis 的 Basic Usage 文档解释说 ConnectionMultiplexer
是长期存在的,预计会被重复使用。
但是当与服务器的连接断开时怎么办? ConnectionMultiplexer
是否自动重新连接,或者是否有必要像 this answer 那样编写代码(引用该答案):
if (RedisConnection == null || !RedisConnection.IsConnected)
{
RedisConnection = ConnectionMultiplexer.Connect(...);
}
RedisCacheDb = RedisConnection.GetDatabase();
上面的代码是否适合处理断开连接的恢复,或者它实际上会导致多个 ConnectionMultiplexer
实例?同样,IsConnected
属性 应该如何解释?
[旁白:我认为上面的代码是一种非常糟糕的惰性初始化形式,尤其是在多线程环境中 - 请参阅 Jon Skeet's article on Singletons]。
是的,您需要这种类型的验证才能修复断开的连接。一些线程安全也应该被考虑在内。这就是我通常这样做的方式:
private static ConnectionMultiplexer _redis;
private static readonly Object _multiplexerLock = new Object();
private void ConnectRedis()
{
try
{
_redis = ConnectionMultiplexer.Connect("...<connection string here>...");
}
catch (Exception ex)
{
//exception handling goes here
}
}
private ConnectionMultiplexer RedisMultiplexer
{
get
{
lock (_multiplexerLock)
{
if (_redis == null || !_redis.IsConnected)
{
ConnectRedis();
}
return _redis;
}
}
}
然后我在需要调用 Redis 端点的任何地方使用 RedisMultiplexer
属性。我通常不存储 GetDatabase()
调用的结果,因为文档说这是一个非常轻量级的调用。
这里是 pattern recommended by the Azure Redis Cache team:
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});
public static ConnectionMultiplexer Connection {
get {
return lazyConnection.Value;
}
}
几个要点:
- 它使用 Lazy
来处理线程安全初始化 - 它设置 "abortConnect=false",这意味着如果初始连接尝试失败,ConnectionMultiplexer 将在后台静默重试而不是抛出异常。
- 它不会检查 IsConnected 属性,因为如果连接断开,ConnectionMultiplexer 将在后台自动重试。