Redis连接可能无法与c#关闭

时间:2016-02-25 02:21:14

标签: azure redis servicestack.redis azure-redis-cache

我正在连接到Azure Redis,他们向我显示了我的redis服务器的打开连接数。我已经获得了以下c#代码,其中包含我所有的Redis集并获取。这应该是泄漏连接吗?

       using (var connectionMultiplexer = ConnectionMultiplexer.Connect(connectionString))
        {

            lock (Locker)
            {
                redis = connectionMultiplexer.GetDatabase();
            }

            var o = CacheSerializer.Deserialize<T>(redis.StringGet(cacheKeyName));
            if (o != null)
            {
                return o;
            }
            lock (Locker)
            {
                // get lock but release if it takes more than 60 seconds to complete to avoid deadlock if this app crashes before release
                //using (redis.AcquireLock(cacheKeyName + "-lock", TimeSpan.FromSeconds(60)))

                var lockKey = cacheKeyName + "-lock";
                if (redis.LockTake(lockKey, Environment.MachineName, TimeSpan.FromSeconds(10)))
                {
                    try
                    {
                        o = CacheSerializer.Deserialize<T>(redis.StringGet(cacheKeyName));
                        if (o == null)
                        {
                            o = func();
                            redis.StringSet(cacheKeyName, CacheSerializer.Serialize(o),
                                TimeSpan.FromSeconds(cacheTimeOutSeconds));
                        }
                        redis.LockRelease(lockKey, Environment.MachineName);
                        return o;
                    }
                    finally
                    {
                        redis.LockRelease(lockKey, Environment.MachineName);
                    }
                }
                return o;
            }

        }
    }

2 个答案:

答案 0 :(得分:5)

您可以将connectionMultiplexer保留在静态变量中,而不是为每个get / set创建它。这将保持与Redis的一个连接始终打开并更快地继续您的操作。

更新: 请看看StackExchange.Redis的基本用法: https://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Basics.md

&#34;请注意,ConnectionMultiplexer实现了IDisposable,并且可以在不再需要时进行处理,但是我故意不显示使用语句,因为您特别想要简单地使用ConnectionMultiplexer,因为我们的想法是重复使用这个对象。&#34;

它对我很好,保持与Azure Redis的单一连接(有时,创建2个连接,但这是设计)。希望它会对你有所帮助。

答案 1 :(得分:0)

我建议尝试显式使用Close(或CloseAsync)方法。在测试设置中,您可能为不同的测试案例使用了不同的连接,并且不想共享一个多路复用器。使用Redis客户端搜索公共代码会显示先关闭后再进行Dispose调用的方式。

Redis客户端的XML方法文档中注意到close方法被描述为可以做更多的事情:

    //
    // Summary:
    //     Close all connections and release all resources associated with this object
    //
    // Parameters:
    //   allowCommandsToComplete:
    //     Whether to allow all in-queue commands to complete first.
    public void Close(bool allowCommandsToComplete = true);
    //
    // Summary:
    //     Close all connections and release all resources associated with this object
    //
    // Parameters:
    //   allowCommandsToComplete:
    //     Whether to allow all in-queue commands to complete first.
    [AsyncStateMachine(typeof(<CloseAsync>d__183))]
    public Task CloseAsync(bool allowCommandsToComplete = true);

...

//
// Summary:
//     Release all resources associated with this object
public void Dispose();

然后我查找了该客户端的代码,在这里找到了它:

https://github.com/StackExchange/StackExchange.Redis/blob/master/src/StackExchange.Redis/ConnectionMultiplexer.cs

我们可以看到Dispose方法调用Close(不是通常的可重写的受保护的Dispose(bool)),还有更多等待连接关闭的设置为true的情况。这似乎是一种非典型的Dispose模式实现,因为尝试所有的关闭并等待它们,而Dispose方法协定应该永远不会抛出异常,这很可能会导致异常。